Repository: rust-analyzer/rust-analyzer
Pull request #8119 (2021-03-20 12:45:26)

 Don't return a SourceChange on WillRenameFiles when nothing gets refactored
bors r+


Patch:
diff --git a/crates/hir/src/attrs.rs b/crates/hir/src/attrs.rs
index 4a11622fc9..dab8da7bbf 100644
--- a/crates/hir/src/attrs.rs
+++ b/crates/hir/src/attrs.rs
@@ -1,6 +1,6 @@
 //! Attributes & documentation for hir types.
 use hir_def::{
-    attr::{AttrsWithOwner, Documentation},
+    attr::{Attrs, Documentation},
     path::ModPath,
     per_ns::PerNs,
     resolver::HasResolver,
@@ -16,7 +16,7 @@ use crate::{
 };
 
 pub trait HasAttrs {
-    fn attrs(self, db: &dyn HirDatabase) -> AttrsWithOwner;
+    fn attrs(self, db: &dyn HirDatabase) -> Attrs;
     fn docs(self, db: &dyn HirDatabase) -> Option<Documentation>;
     fn resolve_doc_path(
         self,
@@ -36,7 +36,7 @@ pub enum Namespace {
 macro_rules! impl_has_attrs {
     ($(($def:ident, $def_id:ident),)*) => {$(
         impl HasAttrs for $def {
-            fn attrs(self, db: &dyn HirDatabase) -> AttrsWithOwner {
+            fn attrs(self, db: &dyn HirDatabase) -> Attrs {
                 let def = AttrDefId::$def_id(self.into());
                 db.attrs(def)
             }
@@ -70,7 +70,7 @@ impl_has_attrs![
 macro_rules! impl_has_attrs_enum {
     ($($variant:ident),* for $enum:ident) => {$(
         impl HasAttrs for $variant {
-            fn attrs(self, db: &dyn HirDatabase) -> AttrsWithOwner {
+            fn attrs(self, db: &dyn HirDatabase) -> Attrs {
                 $enum::$variant(self).attrs(db)
             }
             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 dc10a4d0fa..d57fad9ed3 100644
--- a/crates/hir/src/has_source.rs
+++ b/crates/hir/src/has_source.rs
@@ -6,7 +6,7 @@ use hir_def::{
     src::{HasChildSource, HasSource as _},
     Lookup, VariantId,
 };
-use hir_expand::InFile;
+use hir_expand::{InFile, MacroDefKind};
 use syntax::ast;
 
 use crate::{
@@ -113,10 +113,15 @@ impl HasSource for TypeAlias {
 impl HasSource for MacroDef {
     type Ast = Either<ast::Macro, ast::Fn>;
     fn source(self, db: &dyn HirDatabase) -> Option<InFile<Self::Ast>> {
-        Some(self.id.ast_id().either(
-            |id| id.with_value(Either::Left(id.to_node(db.upcast()))),
-            |id| id.with_value(Either::Right(id.to_node(db.upcast()))),
-        ))
+        Some(match &self.id.kind {
+            MacroDefKind::Declarative(id)
+            | MacroDefKind::BuiltIn(_, id)
+            | MacroDefKind::BuiltInDerive(_, id)
+            | MacroDefKind::BuiltInEager(_, id) => {
+                id.with_value(Either::Left(id.to_node(db.upcast())))
+            }
+            MacroDefKind::ProcMacro(_, id) => id.map(|_| Either::Right(id.to_node(db.upcast()))),
+        })
     }
 }
 impl HasSource for Impl {
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 30e5776712..5ebd0a3b89 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -56,9 +56,9 @@ use hir_ty::{
     primitive::UintTy,
     to_assoc_type_id,
     traits::{FnTrait, Solution, SolutionVariables},
-    AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, Cast, DebruijnIndex,
-    InEnvironment, Interner, ProjectionTy, Scalar, Substitution, Ty, TyDefId, TyKind,
-    TyVariableKind, WhereClause,
+    AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, DebruijnIndex,
+    GenericPredicate, InEnvironment, Interner, Obligation, ProjectionTy, Scalar, Substitution, Ty,
+    TyDefId, TyKind, TyVariableKind,
 };
 use itertools::Itertools;
 use rustc_hash::FxHashSet;
@@ -89,7 +89,7 @@ pub use crate::{
 pub use {
     hir_def::{
         adt::StructKind,
-        attr::{Attr, Attrs, AttrsWithOwner, Documentation},
+        attr::{Attr, Attrs, Documentation},
         body::scope::ExprScopes,
         find_path::PrefixKind,
         import_map,
@@ -1461,7 +1461,7 @@ impl TypeParam {
         db.generic_predicates_for_param(self.id)
             .into_iter()
             .filter_map(|pred| match &pred.value {
-                hir_ty::WhereClause::Implemented(trait_ref) => {
+                hir_ty::GenericPredicate::Implemented(trait_ref) => {
                     Some(Trait::from(trait_ref.hir_trait_id()))
                 }
                 _ => None,
@@ -1767,7 +1767,7 @@ impl Type {
         let goal = Canonical {
             value: hir_ty::InEnvironment::new(
                 self.ty.environment.clone(),
-                trait_ref.cast(&Interner),
+                hir_ty::Obligation::Trait(trait_ref),
             ),
             kinds: Arc::new([]),
         };
@@ -1789,15 +1789,14 @@ impl Type {
         let goal = Canonical {
             value: InEnvironment::new(
                 self.ty.environment.clone(),
-                AliasEq {
+                Obligation::AliasEq(AliasEq {
                     alias: AliasTy::Projection(ProjectionTy {
                         associated_ty_id: to_assoc_type_id(alias.id),
                         substitution: subst,
                     }),
                     ty: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0))
                         .intern(&Interner),
-                }
-                .cast(&Interner),
+                }),
             ),
             kinds: Arc::new([TyVariableKind::General]),
         };
@@ -2023,7 +2022,7 @@ impl Type {
         self.ty.value.impl_trait_bounds(db).map(|it| {
             it.into_iter()
                 .filter_map(|pred| match pred {
-                    hir_ty::WhereClause::Implemented(trait_ref) => {
+                    hir_ty::GenericPredicate::Implemented(trait_ref) => {
                         Some(Trait::from(trait_ref.hir_trait_id()))
                     }
                     _ => None,
@@ -2061,12 +2060,12 @@ impl Type {
         fn walk_bounds(
             db: &dyn HirDatabase,
             type_: &Type,
-            bounds: &[WhereClause],
+            bounds: &[GenericPredicate],
             cb: &mut impl FnMut(Type),
         ) {
             for pred in bounds {
                 match pred {
-                    WhereClause::Implemented(trait_ref) => {
+                    GenericPredicate::Implemented(trait_ref) => {
                         cb(type_.clone());
                         walk_substs(db, type_, &trait_ref.substitution, cb);
                     }
diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs
index 2c10f46d8a..0360fb6270 100644
--- a/crates/hir_def/src/attr.rs
+++ b/crates/hir_def/src/attr.rs
@@ -21,7 +21,7 @@ use crate::{
     item_tree::{ItemTreeId, ItemTreeNode},
     nameres::ModuleSource,
     path::{ModPath, PathKind},
-    src::{HasChildSource, HasSource},
+    src::HasChildSource,
     AdtId, AttrDefId, EnumId, GenericParamId, HasModule, LocalEnumVariantId, LocalFieldId, Lookup,
     VariantId,
 };
@@ -51,12 +51,6 @@ pub(crate) struct RawAttrs {
 #[derive(Default, Debug, Clone, PartialEq, Eq)]
 pub struct Attrs(RawAttrs);
 
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub struct AttrsWithOwner {
-    attrs: Attrs,
-    owner: AttrDefId,
-}
-
 impl ops::Deref for RawAttrs {
     type Target = [Attr];
 
@@ -79,14 +73,6 @@ impl ops::Deref for Attrs {
     }
 }
 
-impl ops::Deref for AttrsWithOwner {
-    type Target = Attrs;
-
-    fn deref(&self) -> &Attrs {
-        &self.attrs
-    }
-}
-
 impl RawAttrs {
     pub(crate) const EMPTY: Self = Self { entries: None };
 
@@ -183,6 +169,77 @@ impl RawAttrs {
 impl Attrs {
     pub const EMPTY: Self = Self(RawAttrs::EMPTY);
 
+    pub(crate) fn attrs_query(db: &dyn DefDatabase, def: AttrDefId) -> Attrs {
+        let raw_attrs = match def {
+            AttrDefId::ModuleId(module) => {
+                let def_map = module.def_map(db);
+                let mod_data = &def_map[module.local_id];
+                match mod_data.declaration_source(db) {
+                    Some(it) => {
+                        let raw_attrs = RawAttrs::from_attrs_owner(
+                            db,
+                            it.as_ref().map(|it| it as &dyn ast::AttrsOwner),
+                        );
+                        match mod_data.definition_source(db) {
+                            InFile { file_id, value: ModuleSource::SourceFile(file) } => raw_attrs
+                                .merge(RawAttrs::from_attrs_owner(db, InFile::new(file_id, &file))),
+                            _ => raw_attrs,
+                        }
+                    }
+                    None => RawAttrs::from_attrs_owner(
+                        db,
+                        mod_data.definition_source(db).as_ref().map(|src| match src {
+                            ModuleSource::SourceFile(file) => file as &dyn ast::AttrsOwner,
+                            ModuleSource::Module(module) => module as &dyn ast::AttrsOwner,
+                            ModuleSource::BlockExpr(block) => block as &dyn ast::AttrsOwner,
+                        }),
+                    ),
+                }
+            }
+            AttrDefId::FieldId(it) => {
+                return db.fields_attrs(it.parent)[it.local_id].clone();
+            }
+            AttrDefId::EnumVariantId(it) => {
+                return db.variants_attrs(it.parent)[it.local_id].clone();
+            }
+            AttrDefId::AdtId(it) => match it {
+                AdtId::StructId(it) => attrs_from_item_tree(it.lookup(db).id, db),
+                AdtId::EnumId(it) => attrs_from_item_tree(it.lookup(db).id, db),
+                AdtId::UnionId(it) => attrs_from_item_tree(it.lookup(db).id, db),
+            },
+            AttrDefId::TraitId(it) => attrs_from_item_tree(it.lookup(db).id, db),
+            AttrDefId::MacroDefId(it) => {
+                it.ast_id().map_or_else(Default::default, |ast_id| attrs_from_ast(ast_id, db))
+            }
+            AttrDefId::ImplId(it) => attrs_from_item_tree(it.lookup(db).id, db),
+            AttrDefId::ConstId(it) => attrs_from_item_tree(it.lookup(db).id, db),
+            AttrDefId::StaticId(it) => attrs_from_item_tree(it.lookup(db).id, db),
+            AttrDefId::FunctionId(it) => attrs_from_item_tree(it.lookup(db).id, db),
+            AttrDefId::TypeAliasId(it) => attrs_from_item_tree(it.lookup(db).id, db),
+            AttrDefId::GenericParamId(it) => match it {
+                GenericParamId::TypeParamId(it) => {
+                    let src = it.parent.child_source(db);
+                    RawAttrs::from_attrs_owner(
+                        db,
+                        src.with_value(
+                            src.value[it.local_id].as_ref().either(|it| it as _, |it| it as _),
+                        ),
+                    )
+                }
+                GenericParamId::LifetimeParamId(it) => {
+                    let src = it.parent.child_source(db);
+                    RawAttrs::from_attrs_owner(db, src.with_value(&src.value[it.local_id]))
+                }
+                GenericParamId::ConstParamId(it) => {
+                    let src = it.parent.child_source(db);
+                    RawAttrs::from_attrs_owner(db, src.with_value(&src.value[it.local_id]))
+                }
+            },
+        };
+
+        raw_attrs.filter(db, def.krate(db))
+    }
+
     pub(crate) fn variants_attrs_query(
         db: &dyn DefDatabase,
         e: EnumId,
@@ -223,6 +280,56 @@ impl Attrs {
         Arc::new(res)
     }
 
+    /// Constructs a map that maps the lowered `Attr`s in this `Attrs` back to its original syntax nodes.
+    ///
+    /// `owner` must be the original owner of the attributes.
+    // FIXME: figure out a better api that doesnt require the for_module hack
+    pub fn source_map(&self, owner: InFile<&dyn ast::AttrsOwner>) -> AttrSourceMap {
+        // FIXME: This doesn't work correctly for modules, as the attributes there can have up to
+        // two different owners
+        AttrSourceMap {
+            attrs: collect_attrs(owner.value)
+                .map(|attr| InFile::new(owner.file_id, attr))
+                .collect(),
+        }
+    }
+
+    pub fn source_map_for_module(
+        &self,
+        db: &dyn DefDatabase,
+        module: crate::ModuleId,
+    ) -> AttrSourceMap {
+        let def_map = module.def_map(db);
+        let mod_data = &def_map[module.local_id];
+        let attrs = match mod_data.declaration_source(db) {
+            Some(it) => {
+                let mut attrs: Vec<_> = collect_attrs(&it.value as &dyn ast::AttrsOwner)
+                    .map(|attr| InFile::new(it.file_id, attr))
+                    .collect();
+                if let InFile { file_id, value: ModuleSource::SourceFile(file) } =
+                    mod_data.definition_source(db)
+                {
+                    attrs.extend(
+                        collect_attrs(&file as &dyn ast::AttrsOwner)
+                            .map(|attr| InFile::new(file_id, attr)),
+                    )
+                }
+                attrs
+            }
+            None => {
+                let InFile { file_id, value } = mod_data.definition_source(db);
+                match &value {
+                    ModuleSource::SourceFile(file) => collect_attrs(file as &dyn ast::AttrsOwner),
+                    ModuleSource::Module(module) => collect_attrs(module as &dyn ast::AttrsOwner),
+                    ModuleSource::BlockExpr(block) => collect_attrs(block as &dyn ast::AttrsOwner),
+                }
+                .map(|attr| InFile::new(file_id, attr))
+                .collect()
+            }
+        };
+        AttrSourceMap { attrs }
+    }
+
     pub fn by_key(&self, key: &'static str) -> AttrQuery<'_> {
         AttrQuery { attrs: self, key }
     }
@@ -279,180 +386,6 @@ impl Attrs {
     }
 }
 
-impl AttrsWithOwner {
-    pub(crate) fn attrs_query(db: &dyn DefDatabase, def: AttrDefId) -> Self {
-        // FIXME: this should use `Trace` to avoid duplication in `source_map` below
-        let raw_attrs = match def {
-            AttrDefId::ModuleId(module) => {
-                let def_map = module.def_map(db);
-                let mod_data = &def_map[module.local_id];
-                match mod_data.declaration_source(db) {
-                    Some(it) => {
-                        let raw_attrs = RawAttrs::from_attrs_owner(
-                            db,
-                            it.as_ref().map(|it| it as &dyn ast::AttrsOwner),
-                        );
-                        match mod_data.definition_source(db) {
-                            InFile { file_id, value: ModuleSource::SourceFile(file) } => raw_attrs
-                                .merge(RawAttrs::from_attrs_owner(db, InFile::new(file_id, &file))),
-                            _ => raw_attrs,
-                        }
-                    }
-                    None => RawAttrs::from_attrs_owner(
-                        db,
-                        mod_data.definition_source(db).as_ref().map(|src| match src {
-                            ModuleSource::SourceFile(file) => file as &dyn ast::AttrsOwner,
-                            ModuleSource::Module(module) => module as &dyn ast::AttrsOwner,
-                            ModuleSource::BlockExpr(block) => block as &dyn ast::AttrsOwner,
-                        }),
-                    ),
-                }
-            }
-            AttrDefId::FieldId(it) => {
-                return Self { attrs: db.fields_attrs(it.parent)[it.local_id].clone(), owner: def };
-            }
-            AttrDefId::EnumVariantId(it) => {
-                return Self {
-                    attrs: db.variants_attrs(it.parent)[it.local_id].clone(),
-                    owner: def,
-                };
-            }
-            AttrDefId::AdtId(it) => match it {
-                AdtId::StructId(it) => attrs_from_item_tree(it.lookup(db).id, db),
-                AdtId::EnumId(it) => attrs_from_item_tree(it.lookup(db).id, db),
-                AdtId::UnionId(it) => attrs_from_item_tree(it.lookup(db).id, db),
-            },
-            AttrDefId::TraitId(it) => attrs_from_item_tree(it.lookup(db).id, db),
-            AttrDefId::MacroDefId(it) => it
-                .ast_id()
-                .left()
-                .map_or_else(Default::default, |ast_id| attrs_from_ast(ast_id, db)),
-            AttrDefId::ImplId(it) => attrs_from_item_tree(it.lookup(db).id, db),
-            AttrDefId::ConstId(it) => attrs_from_item_tree(it.lookup(db).id, db),
-            AttrDefId::StaticId(it) => attrs_from_item_tree(it.lookup(db).id, db),
-            AttrDefId::FunctionId(it) => attrs_from_item_tree(it.lookup(db).id, db),
-            AttrDefId::TypeAliasId(it) => attrs_from_item_tree(it.lookup(db).id, db),
-            AttrDefId::GenericParamId(it) => match it {
-                GenericParamId::TypeParamId(it) => {
-                    let src = it.parent.child_source(db);
-                    RawAttrs::from_attrs_owner(
-                        db,
-                        src.with_value(
-                            src.value[it.local_id].as_ref().either(|it| it as _, |it| it as _),
-                        ),
-                    )
-                }
-                GenericParamId::LifetimeParamId(it) => {
-                    let src = it.parent.child_source(db);
-                    RawAttrs::from_attrs_owner(db, src.with_value(&src.value[it.local_id]))
-                }
-                GenericParamId::ConstParamId(it) => {
-                    let src = it.parent.child_source(db);
-                    RawAttrs::from_attrs_owner(db, src.with_value(&src.value[it.local_id]))
-                }
-            },
-        };
-
-        let attrs = raw_attrs.filter(db, def.krate(db));
-        Self { attrs, owner: def }
-    }
-
-    pub fn source_map(&self, db: &dyn DefDatabase) -> AttrSourceMap {
-        let owner = match self.owner {
-            AttrDefId::ModuleId(module) => {
-                // Modules can have 2 attribute owners (the `mod x;` item, and the module file itself).
-
-                let def_map = module.def_map(db);
-                let mod_data = &def_map[module.local_id];
-                let attrs = match mod_data.declaration_source(db) {
-                    Some(it) => {
-                        let mut attrs: Vec<_> = collect_attrs(&it.value as &dyn ast::AttrsOwner)
-                            .map(|attr| InFile::new(it.file_id, attr))
-                            .collect();
-                        if let InFile { file_id, value: ModuleSource::SourceFile(file) } =
-                            mod_data.definition_source(db)
-                        {
-                            attrs.extend(
-                                collect_attrs(&file as &dyn ast::AttrsOwner)
-                                    .map(|attr| InFile::new(file_id, attr)),
-                            )
-                        }
-                        attrs
-                    }
-                    None => {
-                        let InFile { file_id, value } = mod_data.definition_source(db);
-                        match &value {
-                            ModuleSource::SourceFile(file) => {
-                                collect_attrs(file as &dyn ast::AttrsOwner)
-                            }
-                            ModuleSource::Module(module) => {
-                                collect_attrs(module as &dyn ast::AttrsOwner)
-                            }
-                            ModuleSource::BlockExpr(block) => {
-                                collect_attrs(block as &dyn ast::AttrsOwner)
-                            }
-                        }
-                        .map(|attr| InFile::new(file_id, attr))
-                        .collect()
-                    }
-                };
-                return AttrSourceMap { attrs };
-            }
-            AttrDefId::FieldId(id) => {
-                id.parent.child_source(db).map(|source| match &source[id.local_id] {
-                    Either::Left(field) => ast::AttrsOwnerNode::new(field.clone()),
-                    Either::Right(field) => ast::AttrsOwnerNode::new(field.clone()),
-                })
-            }
-            AttrDefId::AdtId(adt) => match adt {
-                AdtId::StructId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new),
-                AdtId::UnionId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new),
-                AdtId::EnumId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new),
-            },
-            AttrDefId::FunctionId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new),
-            AttrDefId::EnumVariantId(id) => id
-                .parent
-                .child_source(db)
-                .map(|source| ast::AttrsOwnerNode::new(source[id.local_id].clone())),
-            AttrDefId::StaticId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new),
-            AttrDefId::ConstId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new),
-            AttrDefId::TraitId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new),
-            AttrDefId::TypeAliasId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new),
-            AttrDefId::MacroDefId(id) => match id.ast_id() {
-                Either::Left(it) => {
-                    it.with_value(ast::AttrsOwnerNode::new(it.to_node(db.upcast())))
-                }
-                Either::Right(it) => {
-                    it.with_value(ast::AttrsOwnerNode::new(it.to_node(db.upcast())))
-                }
-            },
-            AttrDefId::ImplId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new),
-            AttrDefId::GenericParamId(id) => match id {
-                GenericParamId::TypeParamId(id) => {
-                    id.parent.child_source(db).map(|source| match &source[id.local_id] {
-                        Either::Left(id) => ast::AttrsOwnerNode::new(id.clone()),
-                        Either::Right(id) => ast::AttrsOwnerNode::new(id.clone()),
-                    })
-                }
-                GenericParamId::LifetimeParamId(id) => id
-                    .parent
-                    .child_source(db)
-                    .map(|source| ast::AttrsOwnerNode::new(source[id.local_id].clone())),
-                GenericParamId::ConstParamId(id) => id
-                    .parent
-                    .child_source(db)
-                    .map(|source| ast::AttrsOwnerNode::new(source[id.local_id].clone())),
-            },
-        };
-
-        AttrSourceMap {
-            attrs: collect_attrs(&owner.value)
-                .map(|attr| InFile::new(owner.file_id, attr))
-                .collect(),
-        }
-    }
-}
-
 fn inner_attributes(
     syntax: &SyntaxNode,
 ) -> 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 53df85089a..276caf5b33 100644
--- a/crates/hir_def/src/db.rs
+++ b/crates/hir_def/src/db.rs
@@ -8,7 +8,7 @@ use syntax::SmolStr;
 
 use crate::{
     adt::{EnumData, StructData},
-    attr::{Attrs, AttrsWithOwner},
+    attr::Attrs,
     body::{scope::ExprScopes, Body, BodySourceMap},
     data::{ConstData, FunctionData, ImplData, StaticData, TraitData, TypeAliasData},
     generics::GenericParams,
@@ -120,8 +120,8 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> {
     #[salsa::invoke(Attrs::fields_attrs_query)]
     fn fields_attrs(&self, def: VariantId) -> Arc<ArenaMap<LocalFieldId, Attrs>>;
 
-    #[salsa::invoke(AttrsWithOwner::attrs_query)]
-    fn attrs(&self, def: AttrDefId) -> AttrsWithOwner;
+    #[salsa::invoke(Attrs::attrs_query)]
+    fn attrs(&self, def: AttrDefId) -> Attrs;
 
     #[salsa::invoke(LangItems::crate_lang_items_query)]
     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 46a3c60cdd..4bcdc0fc84 100644
--- a/crates/hir_def/src/nameres/collector.rs
+++ b/crates/hir_def/src/nameres/collector.rs
@@ -1294,37 +1294,29 @@ impl ModCollector<'_, '_> {
                 let db = self.def_collector.db;
                 match self.mod_dir.resolve_declaration(db, self.file_id, &module.name, path_attr) {
                     Ok((file_id, is_mod_rs, mod_dir)) => {
+                        let module_id = self.push_child_module(
+                            module.name.clone(),
+                            ast_id,
+                            Some((file_id, is_mod_rs)),
+                            &self.item_tree[module.visibility],
+                        );
                         let item_tree = db.file_item_tree(file_id.into());
-                        if item_tree
-                            .top_level_attrs(db, self.def_collector.def_map.krate)
-                            .cfg()
-                            .map_or(true, |cfg| {
-                                self.def_collector.cfg_options.check(&cfg) != Some(false)
-                            })
+                        ModCollector {
+                            def_collector: &mut *self.def_collector,
+                            macro_depth: self.macro_depth,
+                            module_id,
+                            file_id: file_id.into(),
+                            item_tree: &item_tree,
+                            mod_dir,
+                        }
+                        .collect(item_tree.top_level_items());
+                        if is_macro_use
+                            || item_tree
+                                .top_level_attrs(db, self.def_collector.def_map.krate)
+                                .by_key("macro_use")
+                                .exists()
                         {
-                            let module_id = self.push_child_module(
-                                module.name.clone(),
-                                ast_id,
-                                Some((file_id, is_mod_rs)),
-                                &self.item_tree[module.visibility],
-                            );
-                            ModCollector {
-                                def_collector: &mut *self.def_collector,
-                                macro_depth: self.macro_depth,
-                                module_id,
-                                file_id: file_id.into(),
-                                item_tree: &item_tree,
-                                mod_dir,
-                            }
-                            .collect(item_tree.top_level_items());
-                            if is_macro_use
-                                || item_tree
-                                    .top_level_attrs(db, self.def_collector.def_map.krate)
-                                    .by_key("macro_use")
-                                    .exists()
-                            {
-                                self.import_all_legacy_macros(module_id);
-                            }
+                            self.import_all_legacy_macros(module_id);
                         }
                     }
                     Err(candidate) => {
diff --git a/crates/hir_expand/src/hygiene.rs b/crates/hir_expand/src/hygiene.rs
index 0e0f7214a2..20cda1683a 100644
--- a/crates/hir_expand/src/hygiene.rs
+++ b/crates/hir_expand/src/hygiene.rs
@@ -145,7 +145,7 @@ fn make_hygiene_info(
 ) -> Option<HygieneInfo> {
     let arg_tt = loc.kind.arg(db)?;
 
-    let def_offset = loc.def.ast_id().left().and_then(|id| {
+    let def_offset = loc.def.ast_id().and_then(|id| {
         let def_tt = match id.to_node(db) {
             ast::Macro::MacroRules(mac) => mac.token_tree()?.syntax().text_range().start(),
             ast::Macro::MacroDef(_) => return None,
diff --git a/crates/hir_expand/src/lib.rs b/crates/hir_expand/src/lib.rs
index f49fd4fda1..c958b08659 100644
--- a/crates/hir_expand/src/lib.rs
+++ b/crates/hir_expand/src/lib.rs
@@ -15,7 +15,6 @@ pub mod proc_macro;
 pub mod quote;
 pub mod eager;
 
-use either::Either;
 pub use mbe::{ExpandError, ExpandResult};
 
 use std::hash::Hash;
@@ -144,7 +143,7 @@ impl HirFileId {
 
                 let arg_tt = loc.kind.arg(db)?;
 
-                let def = loc.def.ast_id().left().and_then(|id| {
+                let def = loc.def.ast_id().and_then(|id| {
                     let def_tt = match id.to_node(db) {
                         ast::Macro::MacroRules(mac) => mac.token_tree()?,
                         ast::Macro::MacroDef(_) => return None,
@@ -240,15 +239,15 @@ impl MacroDefId {
         db.intern_macro(MacroCallLoc { def: self, krate, kind })
     }
 
-    pub fn ast_id(&self) -> Either<AstId<ast::Macro>, AstId<ast::Fn>> {
+    pub fn ast_id(&self) -> Option<AstId<ast::Macro>> {
         let id = match &self.kind {
             MacroDefKind::Declarative(id) => id,
             MacroDefKind::BuiltIn(_, id) => id,
             MacroDefKind::BuiltInDerive(_, id) => id,
             MacroDefKind::BuiltInEager(_, id) => id,
-            MacroDefKind::ProcMacro(_, id) => return Either::Right(*id),
+            MacroDefKind::ProcMacro(..) => return None,
         };
-        Either::Left(*id)
+        Some(*id)
     }
 }
 
diff --git a/crates/hir_ty/src/autoderef.rs b/crates/hir_ty/src/autoderef.rs
index 23ab042c15..33b9660263 100644
--- a/crates/hir_ty/src/autoderef.rs
+++ b/crates/hir_ty/src/autoderef.rs
@@ -6,7 +6,6 @@
 use std::iter::successors;
 
 use base_db::CrateId;
-use chalk_ir::cast::Cast;
 use hir_def::lang_item::LangItemTarget;
 use hir_expand::name::name;
 use log::{info, warn};
@@ -16,8 +15,8 @@ use crate::{
     to_assoc_type_id, to_chalk_trait_id,
     traits::{InEnvironment, Solution},
     utils::generics,
-    AliasEq, AliasTy, BoundVar, Canonical, DebruijnIndex, Interner, ProjectionTy, Substitution,
-    TraitRef, Ty, TyKind,
+    AliasEq, AliasTy, BoundVar, Canonical, DebruijnIndex, Interner, Obligation, ProjectionTy,
+    Substitution, TraitRef, Ty, TyKind,
 };
 
 const AUTODEREF_RECURSION_LIMIT: usize = 10;
@@ -75,7 +74,7 @@ fn deref_by_trait(
     let implements_goal = Canonical {
         kinds: ty.value.kinds.clone(),
         value: InEnvironment {
-            value: trait_ref.cast(&Interner),
+            value: Obligation::Trait(trait_ref),
             environment: ty.environment.clone(),
         },
     };
@@ -93,7 +92,7 @@ fn deref_by_trait(
             .intern(&Interner),
     };
 
-    let obligation = projection.cast(&Interner);
+    let obligation = super::Obligation::AliasEq(projection);
 
     let in_env = InEnvironment { value: obligation, environment: ty.environment };
 
diff --git a/crates/hir_ty/src/chalk_cast.rs b/crates/hir_ty/src/chalk_cast.rs
deleted file mode 100644
index bf884ae158..0000000000
--- a/crates/hir_ty/src/chalk_cast.rs
+++ /dev/null
@@ -1,53 +0,0 @@
-//! Implementations of the Chalk `Cast` trait for our types.
-
-use chalk_ir::{
-    cast::{Cast, CastTo},
-    interner::HasInterner,
-};
-
-use crate::{AliasEq, DomainGoal, Interner, TraitRef, WhereClause};
-
-macro_rules! has_interner {
-    ($t:ty) => {
-        impl HasInterner for $t {
-            type Interner = crate::Interner;
-        }
-    };
-}
-
-has_interner!(WhereClause);
-has_interner!(DomainGoal);
-
-impl CastTo<WhereClause> for TraitRef {
-    fn cast_to(self, _interner: &Interner) -> WhereClause {
-        WhereClause::Implemented(self)
-    }
-}
-
-impl CastTo<WhereClause> for AliasEq {
-    fn cast_to(self, _interner: &Interner) -> WhereClause {
-        WhereClause::AliasEq(self)
-    }
-}
-
-impl CastTo<DomainGoal> for WhereClause {
-    fn cast_to(self, _interner: &Interner) -> DomainGoal {
-        DomainGoal::Holds(self)
-    }
-}
-
-macro_rules! transitive_impl {
-    ($a:ty, $b:ty, $c:ty) => {
-        impl CastTo<$c> for $a {
-            fn cast_to(self, interner: &Interner) -> $c {
-                self.cast::<$b>(interner).cast(interner)
-            }
-        }
-    };
-}
-
-// In Chalk, these can be done as blanket impls, but that doesn't work here
-// because of coherence
-
-transitive_impl!(TraitRef, WhereClause, DomainGoal);
-transitive_impl!(AliasEq, WhereClause, DomainGoal);
diff --git a/crates/hir_ty/src/db.rs b/crates/hir_ty/src/db.rs
index 91a2e0b5be..74a0486721 100644
--- a/crates/hir_ty/src/db.rs
+++ b/crates/hir_ty/src/db.rs
@@ -12,8 +12,8 @@ use la_arena::ArenaMap;
 use crate::{
     method_resolution::{InherentImpls, TraitImpls},
     traits::chalk,
-    Binders, CallableDefId, FnDefId, ImplTraitId, InferenceResult, PolyFnSig, ReturnTypeImplTraits,
-    TraitRef, Ty, TyDefId, ValueTyDefId, WhereClause,
+    Binders, CallableDefId, FnDefId, GenericPredicate, ImplTraitId, InferenceResult, PolyFnSig,
+    ReturnTypeImplTraits, TraitRef, Ty, TyDefId, ValueTyDefId,
 };
 use hir_expand::name::Name;
 
@@ -57,10 +57,13 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
 
     #[salsa::invoke(crate::lower::generic_predicates_for_param_query)]
     #[salsa::cycle(crate::lower::generic_predicates_for_param_recover)]
-    fn generic_predicates_for_param(&self, param_id: TypeParamId) -> Arc<[Binders<WhereClause>]>;
+    fn generic_predicates_for_param(
+        &self,
+        param_id: TypeParamId,
+    ) -> Arc<[Binders<GenericPredicate>]>;
 
     #[salsa::invoke(crate::lower::generic_predicates_query)]
-    fn generic_predicates(&self, def: GenericDefId) -> Arc<[Binders<WhereClause>]>;
+    fn generic_predicates(&self, def: GenericDefId) -> Arc<[Binders<GenericPredicate>]>;
 
     #[salsa::invoke(crate::lower::trait_environment_query)]
     fn trait_environment(&self, def: GenericDefId) -> Arc<crate::TraitEnvironment>;
@@ -119,7 +122,7 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
     fn trait_solve(
         &self,
         krate: CrateId,
-        goal: crate::Canonical<crate::InEnvironment<crate::DomainGoal>>,
+        goal: crate::Canonical<crate::InEnvironment<crate::Obligation>>,
     ) -> Option<crate::traits::Solution>;
 
     #[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 3845009ae7..59a1bd9b0d 100644
--- a/crates/hir_ty/src/display.rs
+++ b/crates/hir_ty/src/display.rs
@@ -19,8 +19,8 @@ use hir_expand::name::Name;
 use crate::{
     db::HirDatabase, from_assoc_type_id, from_foreign_def_id, from_placeholder_idx, primitive,
     to_assoc_type_id, traits::chalk::from_chalk, utils::generics, AdtId, AliasEq, AliasTy,
-    CallableDefId, CallableSig, DomainGoal, ImplTraitId, Interner, Lifetime, OpaqueTy,
-    ProjectionTy, Scalar, Substitution, TraitRef, Ty, TyKind, WhereClause,
+    CallableDefId, CallableSig, GenericPredicate, ImplTraitId, Interner, Lifetime, Obligation,
+    OpaqueTy, ProjectionTy, Scalar, Substitution, TraitRef, Ty, TyKind,
 };
 
 pub struct HirFormatter<'a> {
@@ -353,7 +353,7 @@ impl HirDisplay for Ty {
                     _ => Cow::Borrowed(&[][..]),
                 };
 
-                if let [WhereClause::Implemented(trait_ref), _] = predicates.as_ref() {
+                if let [GenericPredicate::Implemented(trait_ref), _] = predicates.as_ref() {
                     let trait_ = trait_ref.hir_trait_id();
                     if fn_traits(f.db.upcast(), trait_).any(|it| it == trait_) {
                         return write!(f, "{}", ty_display);
@@ -652,7 +652,7 @@ fn fn_traits(db: &dyn DefDatabase, trait_: TraitId) -> impl Iterator<Item = Trai
 
 pub fn write_bounds_like_dyn_trait_with_prefix(
     prefix: &str,
-    predicates: &[WhereClause],
+    predicates: &[GenericPredicate],
     f: &mut HirFormatter,
 ) -> Result<(), HirDisplayError> {
     write!(f, "{}", prefix)?;
@@ -665,7 +665,7 @@ pub fn write_bounds_like_dyn_trait_with_prefix(
 }
 
 fn write_bounds_like_dyn_trait(
-    predicates: &[WhereClause],
+    predicates: &[GenericPredicate],
     f: &mut HirFormatter,
 ) -> Result<(), HirDisplayError> {
     // Note: This code is written to produce nice results (i.e.
@@ -679,7 +679,7 @@ fn write_bounds_like_dyn_trait(
     let mut is_fn_trait = false;
     for p in predicates.iter() {
         match p {
-            WhereClause::Implemented(trait_ref) => {
+            GenericPredicate::Implemented(trait_ref) => {
                 let trait_ = trait_ref.hir_trait_id();
                 if !is_fn_trait {
                     is_fn_trait = fn_traits(f.db.upcast(), trait_).any(|it| it == trait_);
@@ -710,12 +710,12 @@ fn write_bounds_like_dyn_trait(
                     }
                 }
             }
-            WhereClause::AliasEq(alias_eq) if is_fn_trait => {
+            GenericPredicate::AliasEq(alias_eq) if is_fn_trait => {
                 is_fn_trait = false;
                 write!(f, " -> ")?;
                 alias_eq.ty.hir_fmt(f)?;
             }
-            WhereClause::AliasEq(AliasEq { ty, alias }) => {
+            GenericPredicate::AliasEq(AliasEq { ty, alias }) => {
                 // in types in actual Rust, these will always come
                 // after the corresponding Implemented predicate
                 if angle_open {
@@ -731,6 +731,16 @@ fn write_bounds_like_dyn_trait(
                 }
                 ty.hir_fmt(f)?;
             }
+            GenericPredicate::Error => {
+                if angle_open {
+                    // impl Trait<X, {error}>
+                    write!(f, ", ")?;
+                } else if !first {
+                    // impl Trait + {error}
+                    write!(f, " + ")?;
+                }
+                p.hir_fmt(f)?;
+            }
         }
         first = false;
     }
@@ -768,15 +778,18 @@ impl HirDisplay for TraitRef {
     }
 }
 
-impl HirDisplay for WhereClause {
+impl HirDisplay for GenericPredicate {
     fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
         if f.should_truncate() {
             return write!(f, "{}", TYPE_HINT_TRUNCATION);
         }
 
         match self {
-            WhereClause::Implemented(trait_ref) => trait_ref.hir_fmt(f)?,
-            WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => {
+            GenericPredicate::Implemented(trait_ref) => trait_ref.hir_fmt(f)?,
+            GenericPredicate::AliasEq(AliasEq {
+                alias: AliasTy::Projection(projection_ty),
+                ty,
+            }) => {
                 write!(f, "<")?;
                 projection_ty.trait_ref(f.db).hir_fmt_ext(f, true)?;
                 write!(
@@ -786,7 +799,7 @@ impl HirDisplay for WhereClause {
                 )?;
                 ty.hir_fmt(f)?;
             }
-            WhereClause::AliasEq(_) => write!(f, "{{error}}")?,
+            GenericPredicate::AliasEq(_) | GenericPredicate::Error => write!(f, "{{error}}")?,
         }
         Ok(())
     }
@@ -805,12 +818,22 @@ impl HirDisplay for Lifetime {
     }
 }
 
-impl HirDisplay for DomainGoal {
+impl HirDisplay for Obligation {
     fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
         match self {
-            DomainGoal::Holds(wc) => {
-                write!(f, "Holds(")?;
-                wc.hir_fmt(f)?;
+            Obligation::Trait(tr) => {
+                write!(f, "Implements(")?;
+                tr.hir_fmt(f)?;
+                write!(f, ")")
+            }
+            Obligation::AliasEq(AliasEq { alias, ty }) => {
+                write!(f, "Normalize(")?;
+                match alias {
+                    AliasTy::Projection(projection_ty) => projection_ty.hir_fmt(f)?,
+                    AliasTy::Opaque(opaque) => opaque.hir_fmt(f)?,
+                }
+                write!(f, " => ")?;
+                ty.hir_fmt(f)?;
                 write!(f, ")")
             }
         }
diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs
index b9e434c78a..82186979ab 100644
--- a/crates/hir_ty/src/infer.rs
+++ b/crates/hir_ty/src/infer.rs
@@ -18,7 +18,7 @@ use std::mem;
 use std::ops::Index;
 use std::sync::Arc;
 
-use chalk_ir::{cast::Cast, Mutability};
+use chalk_ir::Mutability;
 use hir_def::{
     body::Body,
     data::{ConstData, FunctionData, StaticData},
@@ -37,7 +37,7 @@ use stdx::impl_from;
 use syntax::SmolStr;
 
 use super::{
-    traits::{DomainGoal, Guidance, Solution},
+    traits::{Guidance, Obligation, Solution},
     InEnvironment, ProjectionTy, Substitution, TraitEnvironment, TraitRef, Ty, TypeWalk,
 };
 use crate::{
@@ -204,7 +204,7 @@ struct InferenceContext<'a> {
     resolver: Resolver,
     table: unify::InferenceTable,
     trait_env: Arc<TraitEnvironment>,
-    obligations: Vec<DomainGoal>,
+    obligations: Vec<Obligation>,
     result: InferenceResult,
     /// The return type of the function being inferred, or the closure if we're
     /// currently within one.
@@ -403,8 +403,8 @@ impl<'a> InferenceContext<'a> {
                     }),
                     ty: ty.clone(),
                 };
-                self.obligations.push(trait_ref.cast(&Interner));
-                self.obligations.push(alias_eq.cast(&Interner));
+                self.obligations.push(Obligation::Trait(trait_ref));
+                self.obligations.push(Obligation::AliasEq(alias_eq));
                 self.resolve_ty_as_possible(ty)
             }
             None => self.err_ty(),
@@ -430,7 +430,7 @@ impl<'a> InferenceContext<'a> {
     fn normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty {
         let var = self.table.new_type_var();
         let alias_eq = AliasEq { alias: AliasTy::Projection(proj_ty), ty: var.clone() };
-        let obligation = alias_eq.cast(&Interner);
+        let obligation = Obligation::AliasEq(alias_eq);
         self.obligations.push(obligation);
         var
     }
diff --git a/crates/hir_ty/src/infer/coerce.rs b/crates/hir_ty/src/infer/coerce.rs
index 07eb965739..b86474ed41 100644
--- a/crates/hir_ty/src/infer/coerce.rs
+++ b/crates/hir_ty/src/infer/coerce.rs
@@ -4,11 +4,12 @@
 //!
 //! See: https://doc.rust-lang.org/nomicon/coercions.html
 
-use chalk_ir::{cast::Cast, Mutability, TyVariableKind};
+use chalk_ir::{Mutability, TyVariableKind};
 use hir_def::lang_item::LangItemTarget;
 
 use crate::{
-    autoderef, to_chalk_trait_id, traits::Solution, Interner, Substitution, TraitRef, Ty, TyKind,
+    autoderef, to_chalk_trait_id, traits::Solution, Interner, Obligation, Substitution, TraitRef,
+    Ty, TyKind,
 };
 
 use super::{InEnvironment, InferenceContext};
@@ -142,7 +143,7 @@ impl<'a> InferenceContext<'a> {
             .build();
         let trait_ref =
             TraitRef { trait_id: to_chalk_trait_id(coerce_unsized_trait), substitution: substs };
-        let goal = InEnvironment::new(self.trait_env.clone(), trait_ref.cast(&Interner));
+        let goal = InEnvironment::new(self.trait_env.clone(), Obligation::Trait(trait_ref));
 
         let canonicalizer = self.canonicalizer();
         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 79bbc5daba..93548b6c02 100644
--- a/crates/hir_ty/src/infer/expr.rs
+++ b/crates/hir_ty/src/infer/expr.rs
@@ -3,7 +3,7 @@
 use std::iter::{repeat, repeat_with};
 use std::{mem, sync::Arc};
 
-use chalk_ir::{cast::Cast, Mutability, TyVariableKind};
+use chalk_ir::{Mutability, TyVariableKind};
 use hir_def::{
     expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp},
     path::{GenericArg, GenericArgs},
@@ -21,7 +21,7 @@ use crate::{
     to_assoc_type_id, to_chalk_trait_id,
     traits::{chalk::from_chalk, FnTrait, InEnvironment},
     utils::{generics, variant_data, Generics},
-    AdtId, Binders, CallableDefId, DomainGoal, FnPointer, FnSig, Interner, Rawness, Scalar,
+    AdtId, Binders, CallableDefId, FnPointer, FnSig, Interner, Obligation, Rawness, Scalar,
     Substitution, TraitRef, Ty, TyKind,
 };
 
@@ -90,9 +90,10 @@ impl<'a> InferenceContext<'a> {
             Substitution::build_for_generics(&generic_params).push(ty.clone()).push(arg_ty).build();
 
         let trait_env = Arc::clone(&self.trait_env);
-        let implements_fn_trait: DomainGoal =
-            TraitRef { trait_id: to_chalk_trait_id(fn_once_trait), substitution: substs.clone() }
-                .cast(&Interner);
+        let implements_fn_trait = Obligation::Trait(TraitRef {
+            trait_id: to_chalk_trait_id(fn_once_trait),
+            substitution: substs.clone(),
+        });
         let goal = self.canonicalizer().canonicalize_obligation(InEnvironment {
             value: implements_fn_trait.clone(),
             environment: trait_env,
@@ -937,20 +938,22 @@ impl<'a> InferenceContext<'a> {
             let generic_predicates = self.db.generic_predicates(def.into());
             for predicate in generic_predicates.iter() {
                 let predicate = predicate.clone().subst(parameters);
-                self.obligations.push(predicate.cast(&Interner));
+                if let Some(obligation) = Obligation::from_predicate(predicate) {
+                    self.obligations.push(obligation);
+                }
             }
             // add obligation for trait implementation, if this is a trait method
             match def {
                 CallableDefId::FunctionId(f) => {
                     if let AssocContainerId::TraitId(trait_) = f.lookup(self.db.upcast()).container
                     {
-                        // construct a TraitRef
+                        // construct a TraitDef
                         let substs =
                             parameters.prefix(generics(self.db.upcast(), trait_.into()).len());
-                        self.obligations.push(
-                            TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs }
-                                .cast(&Interner),
-                        );
+                        self.obligations.push(Obligation::Trait(TraitRef {
+                            trait_id: to_chalk_trait_id(trait_),
+                            substitution: substs,
+                        }));
                     }
                 }
                 CallableDefId::StructId(_) | CallableDefId::EnumVariantId(_) => {}
diff --git a/crates/hir_ty/src/infer/path.rs b/crates/hir_ty/src/infer/path.rs
index 58cce56abb..e15135fc1f 100644
--- a/crates/hir_ty/src/infer/path.rs
+++ b/crates/hir_ty/src/infer/path.rs
@@ -2,7 +2,6 @@
 
 use std::iter;
 
-use chalk_ir::cast::Cast;
 use hir_def::{
     path::{Path, PathSegment},
     resolver::{ResolveValueResult, Resolver, TypeNs, ValueNs},
@@ -257,13 +256,10 @@ impl<'a> InferenceContext<'a> {
                             .push(ty.clone())
                             .fill(std::iter::repeat_with(|| self.table.new_type_var()))
                             .build();
-                        self.obligations.push(
-                            TraitRef {
-                                trait_id: to_chalk_trait_id(trait_),
-                                substitution: trait_substs.clone(),
-                            }
-                            .cast(&Interner),
-                        );
+                        self.obligations.push(super::Obligation::Trait(TraitRef {
+                            trait_id: to_chalk_trait_id(trait_),
+                            substitution: trait_substs.clone(),
+                        }));
                         Some(trait_substs)
                     }
                     AssocContainerId::ModuleId(_) => None,
diff --git a/crates/hir_ty/src/infer/unify.rs b/crates/hir_ty/src/infer/unify.rs
index 1fc03c8f42..4738ec08ac 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;
 use chalk_ir::{FloatTy, IntTy, TyVariableKind};
 use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue};
 
-use super::{DomainGoal, InferenceContext};
+use super::{InferenceContext, Obligation};
 use crate::{
-    AliasEq, AliasTy, BoundVar, Canonical, DebruijnIndex, FnPointer, InEnvironment, InferenceVar,
-    Interner, Scalar, Substitution, Ty, TyKind, TypeWalk, WhereClause,
+    AliasEq, AliasTy, BoundVar, Canonical, DebruijnIndex, FnPointer, GenericPredicate,
+    InEnvironment, InferenceVar, Interner, Scalar, Substitution, Ty, TyKind, TypeWalk,
 };
 
 impl<'a> InferenceContext<'a> {
@@ -87,11 +87,14 @@ impl<'a, 'b> Canonicalizer<'a, 'b> {
 
     pub(crate) fn canonicalize_obligation(
         mut self,
-        obligation: InEnvironment<DomainGoal>,
-    ) -> Canonicalized<InEnvironment<DomainGoal>> {
+        obligation: InEnvironment<Obligation>,
+    ) -> Canonicalized<InEnvironment<Obligation>> {
         let result = match obligation.value {
-            DomainGoal::Holds(wc) => {
-                DomainGoal::Holds(self.do_canonicalize(wc, DebruijnIndex::INNERMOST))
+            Obligation::Trait(tr) => {
+                Obligation::Trait(self.do_canonicalize(tr, DebruijnIndex::INNERMOST))
+            }
+            Obligation::AliasEq(alias_eq) => {
+                Obligation::AliasEq(self.do_canonicalize(alias_eq, DebruijnIndex::INNERMOST))
             }
         };
         self.into_canonicalized(InEnvironment {
@@ -379,16 +382,21 @@ impl InferenceTable {
         }
     }
 
-    fn unify_preds(&mut self, pred1: &WhereClause, pred2: &WhereClause, depth: usize) -> bool {
+    fn unify_preds(
+        &mut self,
+        pred1: &GenericPredicate,
+        pred2: &GenericPredicate,
+        depth: usize,
+    ) -> bool {
         match (pred1, pred2) {
-            (WhereClause::Implemented(tr1), WhereClause::Implemented(tr2))
+            (GenericPredicate::Implemented(tr1), GenericPredicate::Implemented(tr2))
                 if tr1.trait_id == tr2.trait_id =>
             {
                 self.unify_substs(&tr1.substitution, &tr2.substitution, depth + 1)
             }
             (
-                WhereClause::AliasEq(AliasEq { alias: alias1, ty: ty1 }),
-                WhereClause::AliasEq(AliasEq { alias: alias2, ty: ty2 }),
+                GenericPredicate::AliasEq(AliasEq { alias: alias1, ty: ty1 }),
+                GenericPredicate::AliasEq(AliasEq { alias: alias2, ty: ty2 }),
             ) => {
                 let (substitution1, substitution2) = match (alias1, alias2) {
                     (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 c46529879d..2afcb54137 100644
--- a/crates/hir_ty/src/lib.rs
+++ b/crates/hir_ty/src/lib.rs
@@ -13,7 +13,6 @@ mod op;
 mod lower;
 pub(crate) mod infer;
 pub(crate) mod utils;
-mod chalk_cast;
 
 pub mod display;
 pub mod db;
@@ -46,11 +45,9 @@ pub use lower::{
     associated_type_shorthand_candidates, callable_item_sig, CallableDefId, ImplTraitLoweringMode,
     TyDefId, TyLoweringContext, ValueTyDefId,
 };
-pub use traits::{AliasEq, DomainGoal, InEnvironment, TraitEnvironment};
+pub use traits::{AliasEq, InEnvironment, Obligation, TraitEnvironment};
 
-pub use chalk_ir::{
-    cast::Cast, AdtId, BoundVar, DebruijnIndex, Mutability, Safety, Scalar, TyVariableKind,
-};
+pub use chalk_ir::{AdtId, BoundVar, DebruijnIndex, Mutability, Safety, Scalar, TyVariableKind};
 
 pub use crate::traits::chalk::Interner;
 
@@ -279,7 +276,7 @@ pub enum TyKind {
     /// represents the `Self` type inside the bounds. This is currently
     /// implicit; Chalk has the `Binders` struct to make it explicit, but it
     /// didn't seem worth the overhead yet.
-    Dyn(Arc<[WhereClause]>),
+    Dyn(Arc<[GenericPredicate]>),
 
     /// A placeholder for a type which could not be computed; this is propagated
     /// to avoid useless error messages. Doubles as a placeholder where type
@@ -567,34 +564,42 @@ impl TypeWalk for TraitRef {
 /// Like `generics::WherePredicate`, but with resolved types: A condition on the
 /// parameters of a generic item.
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub enum WhereClause {
+pub enum GenericPredicate {
     /// The given trait needs to be implemented for its type parameters.
     Implemented(TraitRef),
     /// An associated type bindings like in `Iterator<Item = T>`.
     AliasEq(AliasEq),
+    /// We couldn't resolve the trait reference. (If some type parameters can't
+    /// be resolved, they will just be Unknown).
+    Error,
 }
 
-impl WhereClause {
+impl GenericPredicate {
+    pub fn is_error(&self) -> bool {
+        matches!(self, GenericPredicate::Error)
+    }
+
     pub fn is_implemented(&self) -> bool {
-        matches!(self, WhereClause::Implemented(_))
+        matches!(self, GenericPredicate::Implemented(_))
     }
 
     pub fn trait_ref(&self, db: &dyn HirDatabase) -> Option<TraitRef> {
         match self {
-            WhereClause::Implemented(tr) => Some(tr.clone()),
-            WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(proj), .. }) => {
+            GenericPredicate::Implemented(tr) => Some(tr.clone()),
+            GenericPredicate::AliasEq(AliasEq { alias: AliasTy::Projection(proj), .. }) => {
                 Some(proj.trait_ref(db))
             }
-            WhereClause::AliasEq(_) => None,
+            GenericPredicate::AliasEq(_) | GenericPredicate::Error => None,
         }
     }
 }
 
-impl TypeWalk for WhereClause {
+impl TypeWalk for GenericPredicate {
     fn walk(&self, f: &mut impl FnMut(&Ty)) {
         match self {
-            WhereClause::Implemented(trait_ref) => trait_ref.walk(f),
-            WhereClause::AliasEq(alias_eq) => alias_eq.walk(f),
+            GenericPredicate::Implemented(trait_ref) => trait_ref.walk(f),
+            GenericPredicate::AliasEq(alias_eq) => alias_eq.walk(f),
+            GenericPredicate::Error => {}
         }
     }
 
@@ -604,8 +609,9 @@ impl TypeWalk for WhereClause {
         binders: DebruijnIndex,
     ) {
         match self {
-            WhereClause::Implemented(trait_ref) => trait_ref.walk_mut_binders(f, binders),
-            WhereClause::AliasEq(alias_eq) => alias_eq.walk_mut_binders(f, binders),
+            GenericPredicate::Implemented(trait_ref) => trait_ref.walk_mut_binders(f, binders),
+            GenericPredicate::AliasEq(alias_eq) => alias_eq.walk_mut_binders(f, binders),
+            GenericPredicate::Error => {}
         }
     }
 }
@@ -809,7 +815,7 @@ impl Ty {
     pub fn dyn_trait_ref(&self) -> Option<&TraitRef> {
         match self.interned(&Interner) {
             TyKind::Dyn(bounds) => bounds.get(0).and_then(|b| match b {
-                WhereClause::Implemented(trait_ref) => Some(trait_ref),
+                GenericPredicate::Implemented(trait_ref) => Some(trait_ref),
                 _ => None,
             }),
             _ => None,
@@ -888,7 +894,7 @@ impl Ty {
         }
     }
 
-    pub fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<WhereClause>> {
+    pub fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<GenericPredicate>> {
         match self.interned(&Interner) {
             TyKind::OpaqueType(opaque_ty_id, ..) => {
                 match db.lookup_intern_impl_trait_id((*opaque_ty_id).into()) {
@@ -901,7 +907,7 @@ impl Ty {
                             // This is only used by type walking.
                             // Parameters will be walked outside, and projection predicate is not used.
                             // So just provide the Future trait.
-                            let impl_bound = WhereClause::Implemented(TraitRef {
+                            let impl_bound = GenericPredicate::Implemented(TraitRef {
                                 trait_id: to_chalk_trait_id(future_trait),
                                 substitution: Substitution::empty(),
                             });
@@ -1160,7 +1166,7 @@ pub struct ReturnTypeImplTraits {
 
 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
 pub(crate) struct ReturnTypeImplTrait {
-    pub(crate) bounds: Binders<Vec<WhereClause>>,
+    pub(crate) bounds: Binders<Vec<GenericPredicate>>,
 }
 
 pub fn to_foreign_def_id(id: TypeAliasId) -> ForeignDefId {
diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs
index cbbb535e55..7d22c3df59 100644
--- a/crates/hir_ty/src/lower.rs
+++ b/crates/hir_ty/src/lower.rs
@@ -33,9 +33,9 @@ use crate::{
         all_super_trait_refs, associated_type_by_name_including_super_traits, generics,
         variant_data,
     },
-    AliasEq, AliasTy, Binders, BoundVar, CallableSig, DebruijnIndex, FnPointer, FnSig, ImplTraitId,
-    OpaqueTy, PolyFnSig, ProjectionTy, ReturnTypeImplTrait, ReturnTypeImplTraits, Substitution,
-    TraitEnvironment, TraitRef, Ty, TyKind, TypeWalk, WhereClause,
+    AliasEq, AliasTy, Binders, BoundVar, CallableSig, DebruijnIndex, FnPointer, FnSig,
+    GenericPredicate, ImplTraitId, OpaqueTy, PolyFnSig, ProjectionTy, ReturnTypeImplTrait,
+    ReturnTypeImplTraits, Substitution, TraitEnvironment, TraitRef, Ty, TyKind, TypeWalk,
 };
 
 #[derive(Debug)]
@@ -373,7 +373,8 @@ impl<'a> TyLoweringContext<'a> {
                     // FIXME report error (ambiguous associated type)
                     TyKind::Unknown.intern(&Interner)
                 } else {
-                    TyKind::Dyn(Arc::new([WhereClause::Implemented(trait_ref)])).intern(&Interner)
+                    TyKind::Dyn(Arc::new([GenericPredicate::Implemented(trait_ref)]))
+                        .intern(&Interner)
                 };
                 return (ty, None);
             }
@@ -666,7 +667,7 @@ impl<'a> TyLoweringContext<'a> {
     pub(crate) fn lower_where_predicate(
         &'a self,
         where_predicate: &'a WherePredicate,
-    ) -> impl Iterator<Item = WhereClause> + 'a {
+    ) -> impl Iterator<Item = GenericPredicate> + 'a {
         match where_predicate {
             WherePredicate::ForLifetime { target, bound, .. }
             | WherePredicate::TypeBound { target, bound } => {
@@ -698,15 +699,17 @@ impl<'a> TyLoweringContext<'a> {
         &'a self,
         bound: &'a TypeBound,
         self_ty: Ty,
-    ) -> impl Iterator<Item = WhereClause> + 'a {
+    ) -> impl Iterator<Item = GenericPredicate> + 'a {
         let mut bindings = None;
         let trait_ref = match bound {
             TypeBound::Path(path) => {
                 bindings = self.lower_trait_ref_from_path(path, Some(self_ty));
-                bindings.clone().map(WhereClause::Implemented)
+                Some(
+                    bindings.clone().map_or(GenericPredicate::Error, GenericPredicate::Implemented),
+                )
             }
             TypeBound::Lifetime(_) => None,
-            TypeBound::Error => None,
+            TypeBound::Error => Some(GenericPredicate::Error),
         };
         trait_ref.into_iter().chain(
             bindings
@@ -719,7 +722,7 @@ impl<'a> TyLoweringContext<'a> {
         &'a self,
         bound: &'a TypeBound,
         trait_ref: TraitRef,
-    ) -> impl Iterator<Item = WhereClause> + 'a {
+    ) -> impl Iterator<Item = GenericPredicate> + 'a {
         let last_segment = match bound {
             TypeBound::Path(path) => path.segments().last(),
             TypeBound::Error | TypeBound::Lifetime(_) => None,
@@ -735,7 +738,7 @@ impl<'a> TyLoweringContext<'a> {
                     &binding.name,
                 );
                 let (super_trait_ref, associated_ty) = match found {
-                    None => return SmallVec::<[WhereClause; 1]>::new(),
+                    None => return SmallVec::<[GenericPredicate; 1]>::new(),
                     Some(t) => t,
                 };
                 let projection_ty = ProjectionTy {
@@ -749,7 +752,7 @@ impl<'a> TyLoweringContext<'a> {
                     let ty = self.lower_ty(type_ref);
                     let alias_eq =
                         AliasEq { alias: AliasTy::Projection(projection_ty.clone()), ty };
-                    preds.push(WhereClause::AliasEq(alias_eq));
+                    preds.push(GenericPredicate::AliasEq(alias_eq));
                 }
                 for bound in &binding.bounds {
                     preds.extend(self.lower_type_bound(
@@ -806,7 +809,7 @@ pub fn associated_type_shorthand_candidates<R>(
             let mut traits_: Vec<_> = predicates
                 .iter()
                 .filter_map(|pred| match &pred.value {
-                    WhereClause::Implemented(tr) => Some(tr.clone()),
+                    GenericPredicate::Implemented(tr) => Some(tr.clone()),
                     _ => None,
                 })
                 .collect();
@@ -878,7 +881,7 @@ pub(crate) fn field_types_query(
 pub(crate) fn generic_predicates_for_param_query(
     db: &dyn HirDatabase,
     param_id: TypeParamId,
-) -> Arc<[Binders<WhereClause>]> {
+) -> Arc<[Binders<GenericPredicate>]> {
     let resolver = param_id.parent.resolver(db.upcast());
     let ctx =
         TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable);
@@ -904,7 +907,7 @@ pub(crate) fn generic_predicates_for_param_recover(
     _db: &dyn HirDatabase,
     _cycle: &[String],
     _param_id: &TypeParamId,
-) -> Arc<[Binders<WhereClause>]> {
+) -> Arc<[Binders<GenericPredicate>]> {
     Arc::new([])
 }
 
@@ -919,7 +922,10 @@ pub(crate) fn trait_environment_query(
     let mut clauses = Vec::new();
     for pred in resolver.where_predicates_in_scope() {
         for pred in ctx.lower_where_predicate(pred) {
-            if let WhereClause::Implemented(tr) = &pred {
+            if pred.is_error() {
+                continue;
+            }
+            if let GenericPredicate::Implemented(tr) = &pred {
                 traits_in_scope.push((tr.self_type_parameter().clone(), tr.hir_trait_id()));
             }
             let program_clause: chalk_ir::ProgramClause<Interner> =
@@ -945,7 +951,7 @@ pub(crate) fn trait_environment_query(
         cov_mark::hit!(trait_self_implements_self);
         let substs = Substitution::type_params(db, trait_id);
         let trait_ref = TraitRef { trait_id: to_chalk_trait_id(trait_id), substitution: substs };
-        let pred = WhereClause::Implemented(trait_ref);
+        let pred = GenericPredicate::Implemented(trait_ref);
         let program_clause: chalk_ir::ProgramClause<Interner> =
             pred.clone().to_chalk(db).cast(&Interner);
         clauses.push(program_clause.into_from_env_clause(&Interner));
@@ -960,7 +966,7 @@ pub(crate) fn trait_environment_query(
 pub(crate) fn generic_predicates_query(
     db: &dyn HirDatabase,
     def: GenericDefId,
-) -> Arc<[Binders<WhereClause>]> {
+) -> Arc<[Binders<GenericPredicate>]> {
     let resolver = def.resolver(db.upcast());
     let ctx =
         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 da6bc2a4a1..01b78fb445 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};
 
 use arrayvec::ArrayVec;
 use base_db::CrateId;
-use chalk_ir::{cast::Cast, Mutability};
+use chalk_ir::Mutability;
 use hir_def::{
     lang_item::LangItemTarget, AssocContainerId, AssocItemId, FunctionId, GenericDefId, HasModule,
     ImplId, Lookup, ModuleId, TraitId,
@@ -767,7 +767,7 @@ fn generic_implements_goal(
     env: Arc<TraitEnvironment>,
     trait_: TraitId,
     self_ty: Canonical<Ty>,
-) -> Canonical<InEnvironment<super::DomainGoal>> {
+) -> Canonical<InEnvironment<super::Obligation>> {
     let mut kinds = self_ty.kinds.to_vec();
     let substs = super::Substitution::build_for_def(db, trait_)
         .push(self_ty.value)
@@ -775,7 +775,7 @@ fn generic_implements_goal(
         .build();
     kinds.extend(iter::repeat(chalk_ir::TyVariableKind::General).take(substs.len() - 1));
     let trait_ref = TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs };
-    let obligation = trait_ref.cast(&Interner);
+    let obligation = super::Obligation::Trait(trait_ref);
     Canonical { kinds: kinds.into(), value: InEnvironment::new(env, obligation) }
 }
 
diff --git a/crates/hir_ty/src/traits.rs b/crates/hir_ty/src/traits.rs
index 7dadd1ffba..ac7de76056 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};
 use stdx::panic_context;
 
 use crate::{
-    db::HirDatabase, AliasTy, Canonical, DebruijnIndex, HirDisplay, Substitution, Ty, TyKind,
-    TypeWalk, WhereClause,
+    db::HirDatabase, AliasTy, Canonical, DebruijnIndex, GenericPredicate, HirDisplay, Substitution,
+    TraitRef, Ty, TyKind, TypeWalk,
 };
 
 use self::chalk::{from_chalk, Interner, ToChalk};
@@ -88,8 +88,21 @@ impl<T> InEnvironment<T> {
 /// a certain type implements a certain trait. Proving the Obligation might
 /// result in additional information about inference variables.
 #[derive(Clone, Debug, PartialEq, Eq, Hash)]
-pub enum DomainGoal {
-    Holds(WhereClause),
+pub enum Obligation {
+    /// Prove that a certain type implements a trait (the type is the `Self` type
+    /// parameter to the `TraitRef`).
+    Trait(TraitRef),
+    AliasEq(AliasEq),
+}
+
+impl Obligation {
+    pub fn from_predicate(predicate: GenericPredicate) -> Option<Obligation> {
+        match predicate {
+            GenericPredicate::Implemented(trait_ref) => Some(Obligation::Trait(trait_ref)),
+            GenericPredicate::AliasEq(alias_eq) => Some(Obligation::AliasEq(alias_eq)),
+            GenericPredicate::Error => None,
+        }
+    }
 }
 
 #[derive(Clone, Debug, PartialEq, Eq, Hash)]
@@ -124,20 +137,16 @@ impl TypeWalk for AliasEq {
 pub(crate) fn trait_solve_query(
     db: &dyn HirDatabase,
     krate: CrateId,
-    goal: Canonical<InEnvironment<DomainGoal>>,
+    goal: Canonical<InEnvironment<Obligation>>,
 ) -> Option<Solution> {
     let _p = profile::span("trait_solve_query").detail(|| match &goal.value.value {
-        DomainGoal::Holds(WhereClause::Implemented(it)) => {
-            db.trait_data(it.hir_trait_id()).name.to_string()
-        }
-        DomainGoal::Holds(WhereClause::AliasEq(_)) => "alias_eq".to_string(),
+        Obligation::Trait(it) => db.trait_data(it.hir_trait_id()).name.to_string(),
+        Obligation::AliasEq(_) => "alias_eq".to_string(),
     });
     log::info!("trait_solve_query({})", goal.value.value.display(db));
 
-    if let DomainGoal::Holds(WhereClause::AliasEq(AliasEq {
-        alias: AliasTy::Projection(projection_ty),
-        ..
-    })) = &goal.value.value
+    if let Obligation::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), .. }) =
+        &goal.value.value
     {
         if let TyKind::BoundVar(_) = &projection_ty.substitution[0].interned(&Interner) {
             // 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 734679414b..080764e762 100644
--- a/crates/hir_ty/src/traits/chalk.rs
+++ b/crates/hir_ty/src/traits/chalk.rs
@@ -21,8 +21,8 @@ use crate::{
     method_resolution::{TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS},
     to_assoc_type_id, to_chalk_trait_id,
     utils::generics,
-    AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, DebruijnIndex, FnDefId, ProjectionTy,
-    Substitution, TraitRef, Ty, TyKind, WhereClause,
+    AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, DebruijnIndex, FnDefId,
+    GenericPredicate, ProjectionTy, Substitution, TraitRef, Ty, TyKind,
 };
 use mapping::{
     convert_where_clauses, generic_predicate_to_inline_bound, make_binders, TypeAliasAsValue,
@@ -187,7 +187,13 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
                 let data = &datas.value.impl_traits[idx as usize];
                 let bound = OpaqueTyDatumBound {
                     bounds: make_binders(
-                        data.bounds.value.iter().cloned().map(|b| b.to_chalk(self.db)).collect(),
+                        data.bounds
+                            .value
+                            .iter()
+                            .cloned()
+                            .filter(|b| !b.is_error())
+                            .map(|b| b.to_chalk(self.db))
+                            .collect(),
                         1,
                     ),
                     where_clauses: make_binders(vec![], 0),
@@ -212,7 +218,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
                     //        |-------------OpaqueTyDatumBound--------------|
                     // for<T> <Self> [Future<Self>, Future::Output<Self> = T]
                     //     ^1  ^0            ^0                    ^0      ^1
-                    let impl_bound = WhereClause::Implemented(TraitRef {
+                    let impl_bound = GenericPredicate::Implemented(TraitRef {
                         trait_id: to_chalk_trait_id(future_trait),
                         // Self type as the first parameter.
                         substitution: Substitution::single(
@@ -223,7 +229,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
                             .intern(&Interner),
                         ),
                     });
-                    let proj_bound = WhereClause::AliasEq(AliasEq {
+                    let proj_bound = GenericPredicate::AliasEq(AliasEq {
                         alias: AliasTy::Projection(ProjectionTy {
                             associated_ty_id: to_assoc_type_id(future_output),
                             // 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 65feb82e59..62b779008f 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::{
     db::HirDatabase,
     from_assoc_type_id,
     primitive::UintTy,
-    traits::{Canonical, DomainGoal},
-    AliasTy, CallableDefId, FnPointer, InEnvironment, OpaqueTy, ProjectionTy, Scalar, Substitution,
-    TraitRef, Ty, WhereClause,
+    traits::{Canonical, Obligation},
+    AliasTy, CallableDefId, FnPointer, GenericPredicate, InEnvironment, OpaqueTy, ProjectionTy,
+    Scalar, Substitution, TraitRef, Ty,
 };
 
 use super::interner::*;
@@ -98,7 +98,7 @@ impl ToChalk for Ty {
             TyKind::Dyn(predicates) => {
                 let where_clauses = chalk_ir::QuantifiedWhereClauses::from_iter(
                     &Interner,
-                    predicates.iter().cloned().map(|p| p.to_chalk(db)),
+                    predicates.iter().filter(|p| !p.is_error()).cloned().map(|p| p.to_chalk(db)),
                 );
                 let bounded_ty = chalk_ir::DynTy {
                     bounds: make_binders(where_clauses, 1),
@@ -304,27 +304,28 @@ impl ToChalk for TypeAliasAsValue {
     }
 }
 
-impl ToChalk for WhereClause {
+impl ToChalk for GenericPredicate {
     type Chalk = chalk_ir::QuantifiedWhereClause<Interner>;
 
     fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::QuantifiedWhereClause<Interner> {
         match self {
-            WhereClause::Implemented(trait_ref) => {
+            GenericPredicate::Implemented(trait_ref) => {
                 let chalk_trait_ref = trait_ref.to_chalk(db);
                 let chalk_trait_ref = chalk_trait_ref.shifted_in(&Interner);
                 make_binders(chalk_ir::WhereClause::Implemented(chalk_trait_ref), 0)
             }
-            WhereClause::AliasEq(alias_eq) => make_binders(
+            GenericPredicate::AliasEq(alias_eq) => make_binders(
                 chalk_ir::WhereClause::AliasEq(alias_eq.to_chalk(db).shifted_in(&Interner)),
                 0,
             ),
+            GenericPredicate::Error => panic!("tried passing GenericPredicate::Error to Chalk"),
         }
     }
 
     fn from_chalk(
         db: &dyn HirDatabase,
         where_clause: chalk_ir::QuantifiedWhereClause<Interner>,
-    ) -> WhereClause {
+    ) -> GenericPredicate {
         // we don't produce any where clauses with binders and can't currently deal with them
         match where_clause
             .skip_binders()
@@ -332,9 +333,11 @@ impl ToChalk for WhereClause {
             .shifted_out(&Interner)
             .expect("unexpected bound vars in where clause")
         {
-            chalk_ir::WhereClause::Implemented(tr) => WhereClause::Implemented(from_chalk(db, tr)),
+            chalk_ir::WhereClause::Implemented(tr) => {
+                GenericPredicate::Implemented(from_chalk(db, tr))
+            }
             chalk_ir::WhereClause::AliasEq(alias_eq) => {
-                WhereClause::AliasEq(from_chalk(db, alias_eq))
+                GenericPredicate::AliasEq(from_chalk(db, alias_eq))
             }
 
             chalk_ir::WhereClause::LifetimeOutlives(_) => {
@@ -422,15 +425,13 @@ impl ToChalk for AliasEq {
     }
 }
 
-impl ToChalk for DomainGoal {
+impl ToChalk for Obligation {
     type Chalk = chalk_ir::DomainGoal<Interner>;
 
     fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::DomainGoal<Interner> {
         match self {
-            DomainGoal::Holds(WhereClause::Implemented(tr)) => tr.to_chalk(db).cast(&Interner),
-            DomainGoal::Holds(WhereClause::AliasEq(alias_eq)) => {
-                alias_eq.to_chalk(db).cast(&Interner)
-            }
+            Obligation::Trait(tr) => tr.to_chalk(db).cast(&Interner),
+            Obligation::AliasEq(alias_eq) => alias_eq.to_chalk(db).cast(&Interner),
         }
     }
 
@@ -522,6 +523,10 @@ pub(super) fn convert_where_clauses(
     let generic_predicates = db.generic_predicates(def);
     let mut result = Vec::with_capacity(generic_predicates.len());
     for pred in generic_predicates.iter() {
+        if pred.value.is_error() {
+            // skip errored predicates completely
+            continue;
+        }
         result.push(pred.clone().subst(substs).to_chalk(db));
     }
     result
@@ -529,13 +534,13 @@ pub(super) fn convert_where_clauses(
 
 pub(super) fn generic_predicate_to_inline_bound(
     db: &dyn HirDatabase,
-    pred: &WhereClause,
+    pred: &GenericPredicate,
     self_ty: &Ty,
 ) -> Option<rust_ir::InlineBound<Interner>> {
     // An InlineBound is like a GenericPredicate, except the self type is left out.
     // We don't have a special type for this, but Chalk does.
     match pred {
-        WhereClause::Implemented(trait_ref) => {
+        GenericPredicate::Implemented(trait_ref) => {
             if &trait_ref.substitution[0] != self_ty {
                 // we can only convert predicates back to type bounds if they
                 // have the expected self type
@@ -548,7 +553,7 @@ pub(super) fn generic_predicate_to_inline_bound(
             let trait_bound = rust_ir::TraitBound { trait_id: trait_ref.trait_id, args_no_self };
             Some(rust_ir::InlineBound::TraitBound(trait_bound))
         }
-        WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => {
+        GenericPredicate::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => {
             if &projection_ty.substitution[0] != self_ty {
                 return None;
             }
diff --git a/crates/hir_ty/src/utils.rs b/crates/hir_ty/src/utils.rs
index 1ec1ecd432..b66243d488 100644
--- a/crates/hir_ty/src/utils.rs
+++ b/crates/hir_ty/src/utils.rs
@@ -15,7 +15,7 @@ use hir_def::{
 };
 use hir_expand::name::{name, Name};
 
-use crate::{db::HirDatabase, TraitRef, WhereClause};
+use crate::{db::HirDatabase, GenericPredicate, TraitRef};
 
 fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> {
     let resolver = trait_.resolver(db);
@@ -64,7 +64,7 @@ fn direct_super_trait_refs(db: &dyn HirDatabase, trait_ref: &TraitRef) -> Vec<Tr
         .iter()
         .filter_map(|pred| {
             pred.as_ref().filter_map(|pred| match pred {
-                WhereClause::Implemented(tr) => Some(tr.clone()),
+                GenericPredicate::Implemented(tr) => Some(tr.clone()),
                 _ => None,
             })
         })
diff --git a/crates/ide/src/syntax_highlighting/inject.rs b/crates/ide/src/syntax_highlighting/inject.rs
index 00493a6b57..5722dea3ab 100644
--- a/crates/ide/src/syntax_highlighting/inject.rs
+++ b/crates/ide/src/syntax_highlighting/inject.rs
@@ -6,7 +6,7 @@ use either::Either;
 use hir::{HasAttrs, InFile, Semantics};
 use ide_db::{call_info::ActiveParameter, defs::Definition, SymbolKind};
 use syntax::{
-    ast::{self, AstNode},
+    ast::{self, AstNode, AttrsOwner, DocCommentsOwner},
     match_ast, AstToken, NodeOrToken, SyntaxNode, SyntaxToken, TextRange, TextSize,
 };
 
@@ -89,27 +89,57 @@ const RUSTDOC_FENCE_TOKENS: &[&'static str] = &[
     "edition2021",
 ];
 
+// Basically an owned dyn AttrsOwner without extra Boxing
+struct AttrsOwnerNode {
+    node: SyntaxNode,
+}
+
+impl AttrsOwnerNode {
+    fn new<N: DocCommentsOwner>(node: N) -> Self {
+        AttrsOwnerNode { node: node.syntax().clone() }
+    }
+}
+
+impl AttrsOwner for AttrsOwnerNode {}
+impl AstNode for AttrsOwnerNode {
+    fn can_cast(_: syntax::SyntaxKind) -> bool
+    where
+        Self: Sized,
+    {
+        false
+    }
+    fn cast(_: SyntaxNode) -> Option<Self>
+    where
+        Self: Sized,
+    {
+        None
+    }
+    fn syntax(&self) -> &SyntaxNode {
+        &self.node
+    }
+}
+
 fn doc_attributes<'node>(
     sema: &Semantics<RootDatabase>,
     node: &'node SyntaxNode,
-) -> Option<(hir::AttrsWithOwner, Definition)> {
+) -> Option<(AttrsOwnerNode, hir::Attrs, Definition)> {
     match_ast! {
         match node {
-            ast::SourceFile(it)  => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Module(def)))),
-            ast::Module(it)      => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Module(def)))),
-            ast::Fn(it)          => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Function(def)))),
-            ast::Struct(it)      => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Adt(hir::Adt::Struct(def))))),
-            ast::Union(it)       => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Adt(hir::Adt::Union(def))))),
-            ast::Enum(it)        => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Adt(hir::Adt::Enum(def))))),
-            ast::Variant(it)     => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Variant(def)))),
-            ast::Trait(it)       => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Trait(def)))),
-            ast::Static(it)      => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Static(def)))),
-            ast::Const(it)       => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Const(def)))),
-            ast::TypeAlias(it)   => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::TypeAlias(def)))),
-            ast::Impl(it)        => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::SelfType(def))),
-            ast::RecordField(it) => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::Field(def))),
-            ast::TupleField(it)  => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::Field(def))),
-            ast::MacroRules(it)  => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::Macro(def))),
+            ast::SourceFile(it)  => sema.to_def(&it).map(|def| (AttrsOwnerNode::new(it), def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Module(def)))),
+            ast::Module(it)      => sema.to_def(&it).map(|def| (AttrsOwnerNode::new(it), def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Module(def)))),
+            ast::Fn(it)          => sema.to_def(&it).map(|def| (AttrsOwnerNode::new(it), def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Function(def)))),
+            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))))),
+            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))))),
+            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))))),
+            ast::Variant(it)     => sema.to_def(&it).map(|def| (AttrsOwnerNode::new(it), def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Variant(def)))),
+            ast::Trait(it)       => sema.to_def(&it).map(|def| (AttrsOwnerNode::new(it), def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Trait(def)))),
+            ast::Static(it)      => sema.to_def(&it).map(|def| (AttrsOwnerNode::new(it), def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Static(def)))),
+            ast::Const(it)       => sema.to_def(&it).map(|def| (AttrsOwnerNode::new(it), def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Const(def)))),
+            ast::TypeAlias(it)   => sema.to_def(&it).map(|def| (AttrsOwnerNode::new(it), def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::TypeAlias(def)))),
+            ast::Impl(it)        => sema.to_def(&it).map(|def| (AttrsOwnerNode::new(it), def.attrs(sema.db), Definition::SelfType(def))),
+            ast::RecordField(it) => sema.to_def(&it).map(|def| (AttrsOwnerNode::new(it), def.attrs(sema.db), Definition::Field(def))),
+            ast::TupleField(it)  => sema.to_def(&it).map(|def| (AttrsOwnerNode::new(it), def.attrs(sema.db), Definition::Field(def))),
+            ast::MacroRules(it)  => sema.to_def(&it).map(|def| (AttrsOwnerNode::new(it), def.attrs(sema.db), Definition::Macro(def))),
             // ast::MacroDef(it) => sema.to_def(&it).map(|def| (Box::new(it) as _, def.attrs(sema.db))),
             // ast::Use(it) => sema.to_def(&it).map(|def| (Box::new(it) as _, def.attrs(sema.db))),
             _ => return None
@@ -123,7 +153,7 @@ pub(super) fn doc_comment(
     sema: &Semantics<RootDatabase>,
     node: InFile<&SyntaxNode>,
 ) {
-    let (attributes, def) = match doc_attributes(sema, node.value) {
+    let (owner, attributes, def) = match doc_attributes(sema, node.value) {
         Some(it) => it,
         None => return,
     };
@@ -131,7 +161,12 @@ pub(super) fn doc_comment(
     let mut inj = Injector::default();
     inj.add_unmapped("fn doctest() {\n");
 
-    let attrs_source_map = attributes.source_map(sema.db);
+    let attrs_source_map = match def {
+        Definition::ModuleDef(hir::ModuleDef::Module(module)) => {
+            attributes.source_map_for_module(sema.db, module.into())
+        }
+        _ => attributes.source_map(node.with_value(&owner)),
+    };
 
     let mut is_codeblock = false;
     let mut is_doctest = false;
diff --git a/crates/ide_assists/src/handlers/add_lifetime_to_type.rs b/crates/ide_assists/src/handlers/add_lifetime_to_type.rs
index 2edf7b204b..844928754f 100644
--- a/crates/ide_assists/src/handlers/add_lifetime_to_type.rs
+++ b/crates/ide_assists/src/handlers/add_lifetime_to_type.rs
@@ -29,8 +29,7 @@ pub(crate) fn add_lifetime_to_type(acc: &mut Assists, ctx: &AssistContext) -> Op
     let node = ctx.find_node_at_offset::<ast::Adt>()?;
     let has_lifetime = node
         .generic_param_list()
-        .map(|gen_list| gen_list.lifetime_params().count() > 0)
-        .unwrap_or_default();
+        .map_or(false, |gen_list| gen_list.lifetime_params().next().is_some());
 
     if has_lifetime {
         return None;
@@ -41,7 +40,7 @@ pub(crate) fn add_lifetime_to_type(acc: &mut Assists, ctx: &AssistContext) -> Op
 
     acc.add(
         AssistId("add_lifetime_to_type", AssistKind::Generate),
-        "Add lifetime`",
+        "Add lifetime",
         target,
         |builder| {
             match node.generic_param_list() {
diff --git a/crates/ide_assists/src/handlers/add_turbo_fish.rs b/crates/ide_assists/src/handlers/add_turbo_fish.rs
index 4367678954..e4bb61c4e1 100644
--- a/crates/ide_assists/src/handlers/add_turbo_fish.rs
+++ b/crates/ide_assists/src/handlers/add_turbo_fish.rs
@@ -26,7 +26,7 @@ use crate::{
 pub(crate) fn add_turbo_fish(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
     let ident = ctx.find_token_syntax_at_offset(SyntaxKind::IDENT).or_else(|| {
         let arg_list = ctx.find_node_at_offset::<ast::ArgList>()?;
-        if arg_list.args().count() > 0 {
+        if arg_list.args().next().is_some() {
             return None;
         }
         cov_mark::hit!(add_turbo_fish_after_call);
diff --git a/crates/ide_assists/src/handlers/move_bounds.rs b/crates/ide_assists/src/handlers/move_bounds.rs
index b5dec80147..9ad0c98168 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
 
             for type_param in type_param_list.type_params() {
                 if let Some(tbl) = type_param.type_bound_list() {
-                    if let Some(predicate) = build_predicate(type_param) {
-                        where_clause.add_predicate(predicate)
+                    if let Some(predicate) = build_predicate(type_param.clone()) {
+                        where_clause.add_predicate(predicate.clone_for_update())
                     }
                     tbl.remove()
                 }
@@ -69,7 +69,7 @@ fn build_predicate(param: ast::TypeParam) -> Option<ast::WherePred> {
         make::path_unqualified(segment)
     };
     let predicate = make::where_pred(path, param.type_bound_list()?.bounds());
-    Some(predicate.clone_for_update())
+    Some(predicate)
 }
 
 #[cfg(test)]
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs
index b6f484e515..880fea6220 100644
--- a/crates/rust-analyzer/src/handlers.rs
+++ b/crates/rust-analyzer/src/handlers.rs
@@ -465,8 +465,11 @@ pub(crate) fn handle_will_rename_files(
     source_change.file_system_edits.clear();
     // no collect here because we want to merge text edits on same file ids
     source_change.extend(source_changes.map(|it| it.source_file_edits).flatten());
-    let workspace_edit = to_proto::workspace_edit(&snap, source_change)?;
-    Ok(Some(workspace_edit))
+    if source_change.source_file_edits.is_empty() {
+        Ok(None)
+    } else {
+        to_proto::workspace_edit(&snap, source_change).map(Some)
+    }
 }
 
 pub(crate) fn handle_goto_definition(
diff --git a/crates/syntax/src/ast.rs b/crates/syntax/src/ast.rs
index 7f472d4dbe..38e0b04efb 100644
--- a/crates/syntax/src/ast.rs
+++ b/crates/syntax/src/ast.rs
@@ -20,8 +20,8 @@ pub use self::{
     expr_ext::{ArrayExprKind, BinOp, Effect, ElseBranch, LiteralKind, PrefixOp, RangeOp},
     generated::{nodes::*, tokens::*},
     node_ext::{
-        AttrKind, AttrsOwnerNode, FieldKind, Macro, NameLike, NameOrNameRef, PathSegmentKind,
-        SelfParamKind, SlicePatComponents, StructKind, TypeBoundKind, VisibilityKind,
+        AttrKind, FieldKind, Macro, NameLike, NameOrNameRef, PathSegmentKind, SelfParamKind,
+        SlicePatComponents, StructKind, TypeBoundKind, VisibilityKind,
     },
     token_ext::*,
     traits::*,
diff --git a/crates/syntax/src/ast/edit_in_place.rs b/crates/syntax/src/ast/edit_in_place.rs
index b1eed0a2cc..449b058fbc 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;
 use crate::{
     ast,
     ted::{self, Position},
-    AstNode, Direction,
+    AstNode, Direction, SyntaxElement,
 };
 
 use super::NameOwner;
@@ -21,11 +21,11 @@ impl GenericParamsOwnerEdit for ast::Fn {
     fn get_or_create_where_clause(&self) -> WhereClause {
         if self.where_clause().is_none() {
             let position = if let Some(ty) = self.ret_type() {
-                Position::after(ty.syntax())
+                Position::after(ty.syntax().clone())
             } else if let Some(param_list) = self.param_list() {
-                Position::after(param_list.syntax())
+                Position::after(param_list.syntax().clone())
             } else {
-                Position::last_child_of(self.syntax())
+                Position::last_child_of(self.syntax().clone())
             };
             create_where_clause(position)
         }
@@ -37,9 +37,9 @@ impl GenericParamsOwnerEdit for ast::Impl {
     fn get_or_create_where_clause(&self) -> WhereClause {
         if self.where_clause().is_none() {
             let position = if let Some(items) = self.assoc_item_list() {
-                Position::before(items.syntax())
+                Position::before(items.syntax().clone())
             } else {
-                Position::last_child_of(self.syntax())
+                Position::last_child_of(self.syntax().clone())
             };
             create_where_clause(position)
         }
@@ -51,9 +51,9 @@ impl GenericParamsOwnerEdit for ast::Trait {
     fn get_or_create_where_clause(&self) -> WhereClause {
         if self.where_clause().is_none() {
             let position = if let Some(items) = self.assoc_item_list() {
-                Position::before(items.syntax())
+                Position::before(items.syntax().clone())
             } else {
-                Position::last_child_of(self.syntax())
+                Position::last_child_of(self.syntax().clone())
             };
             create_where_clause(position)
         }
@@ -69,13 +69,13 @@ impl GenericParamsOwnerEdit for ast::Struct {
                 ast::FieldList::TupleFieldList(it) => Some(it),
             });
             let position = if let Some(tfl) = tfl {
-                Position::after(tfl.syntax())
+                Position::after(tfl.syntax().clone())
             } else if let Some(gpl) = self.generic_param_list() {
-                Position::after(gpl.syntax())
+                Position::after(gpl.syntax().clone())
             } else if let Some(name) = self.name() {
-                Position::after(name.syntax())
+                Position::after(name.syntax().clone())
             } else {
-                Position::last_child_of(self.syntax())
+                Position::last_child_of(self.syntax().clone())
             };
             create_where_clause(position)
         }
@@ -87,11 +87,11 @@ impl GenericParamsOwnerEdit for ast::Enum {
     fn get_or_create_where_clause(&self) -> WhereClause {
         if self.where_clause().is_none() {
             let position = if let Some(gpl) = self.generic_param_list() {
-                Position::after(gpl.syntax())
+                Position::after(gpl.syntax().clone())
             } else if let Some(name) = self.name() {
-                Position::after(name.syntax())
+                Position::after(name.syntax().clone())
             } else {
-                Position::last_child_of(self.syntax())
+                Position::last_child_of(self.syntax().clone())
             };
             create_where_clause(position)
         }
@@ -100,18 +100,19 @@ impl GenericParamsOwnerEdit for ast::Enum {
 }
 
 fn create_where_clause(position: Position) {
-    let where_clause = make::where_clause(empty()).clone_for_update();
-    ted::insert(position, where_clause.syntax());
+    let where_clause: SyntaxElement =
+        make::where_clause(empty()).clone_for_update().syntax().clone().into();
+    ted::insert(position, where_clause);
 }
 
 impl ast::WhereClause {
     pub fn add_predicate(&self, predicate: ast::WherePred) {
         if let Some(pred) = self.predicates().last() {
             if !pred.syntax().siblings_with_tokens(Direction::Next).any(|it| it.kind() == T![,]) {
-                ted::append_child_raw(self.syntax(), make::token(T![,]));
+                ted::append_child_raw(self.syntax().clone(), make::token(T![,]));
             }
         }
-        ted::append_child(self.syntax(), predicate.syntax())
+        ted::append_child(self.syntax().clone(), predicate.syntax().clone())
     }
 }
 
@@ -122,7 +123,7 @@ impl ast::TypeBoundList {
         {
             ted::remove_all(colon..=self.syntax().clone().into())
         } else {
-            ted::remove(self.syntax())
+            ted::remove(self.syntax().clone())
         }
     }
 }
diff --git a/crates/syntax/src/ast/node_ext.rs b/crates/syntax/src/ast/node_ext.rs
index 01f580a409..5a9834cbb8 100644
--- a/crates/syntax/src/ast/node_ext.rs
+++ b/crates/syntax/src/ast/node_ext.rs
@@ -90,36 +90,6 @@ impl NameOwner for Macro {
 
 impl AttrsOwner for Macro {}
 
-/// Basically an owned `dyn AttrsOwner` without extra boxing.
-pub struct AttrsOwnerNode {
-    node: SyntaxNode,
-}
-
-impl AttrsOwnerNode {
-    pub fn new<N: AttrsOwner>(node: N) -> Self {
-        AttrsOwnerNode { node: node.syntax().clone() }
-    }
-}
-
-impl AttrsOwner for AttrsOwnerNode {}
-impl AstNode for AttrsOwnerNode {
-    fn can_cast(_: SyntaxKind) -> bool
-    where
-        Self: Sized,
-    {
-        false
-    }
-    fn cast(_: SyntaxNode) -> Option<Self>
-    where
-        Self: Sized,
-    {
-        None
-    }
-    fn syntax(&self) -> &SyntaxNode {
-        &self.node
-    }
-}
-
 #[derive(Debug, Clone, PartialEq, Eq)]
 pub enum AttrKind {
     Inner,
diff --git a/crates/syntax/src/ted.rs b/crates/syntax/src/ted.rs
index be2b846b15..442dfa14ae 100644
--- a/crates/syntax/src/ted.rs
+++ b/crates/syntax/src/ted.rs
@@ -8,33 +8,6 @@ use parser::T;
 
 use crate::{ast::make, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken};
 
-/// Utility trait to allow calling `ted` functions with references or owned
-/// nodes. Do not use outside of this module.
-pub trait Element {
-    fn syntax_element(self) -> SyntaxElement;
-}
-
-impl<E: Element + Clone> Element for &'_ E {
-    fn syntax_element(self) -> SyntaxElement {
-        self.clone().syntax_element()
-    }
-}
-impl Element for SyntaxElement {
-    fn syntax_element(self) -> SyntaxElement {
-        self
-    }
-}
-impl Element for SyntaxNode {
-    fn syntax_element(self) -> SyntaxElement {
-        self.into()
-    }
-}
-impl Element for SyntaxToken {
-    fn syntax_element(self) -> SyntaxElement {
-        self.into()
-    }
-}
-
 #[derive(Debug)]
 pub struct Position {
     repr: PositionRepr,
@@ -47,24 +20,24 @@ enum PositionRepr {
 }
 
 impl Position {
-    pub fn after(elem: impl Element) -> Position {
-        let repr = PositionRepr::After(elem.syntax_element());
+    pub fn after(elem: impl Into<SyntaxElement>) -> Position {
+        let repr = PositionRepr::After(elem.into());
         Position { repr }
     }
-    pub fn before(elem: impl Element) -> Position {
-        let elem = elem.syntax_element();
+    pub fn before(elem: impl Into<SyntaxElement>) -> Position {
+        let elem = elem.into();
         let repr = match elem.prev_sibling_or_token() {
             Some(it) => PositionRepr::After(it),
             None => PositionRepr::FirstChild(elem.parent().unwrap()),
         };
         Position { repr }
     }
-    pub fn first_child_of(node: &(impl Into<SyntaxNode> + Clone)) -> Position {
-        let repr = PositionRepr::FirstChild(node.clone().into());
+    pub fn first_child_of(node: impl Into<SyntaxNode>) -> Position {
+        let repr = PositionRepr::FirstChild(node.into());
         Position { repr }
     }
-    pub fn last_child_of(node: &(impl Into<SyntaxNode> + Clone)) -> Position {
-        let node = node.clone().into();
+    pub fn last_child_of(node: impl Into<SyntaxNode>) -> Position {
+        let node = node.into();
         let repr = match node.last_child_or_token() {
             Some(it) => PositionRepr::After(it),
             None => PositionRepr::FirstChild(node),
@@ -73,11 +46,11 @@ impl Position {
     }
 }
 
-pub fn insert(position: Position, elem: impl Element) {
-    insert_all(position, vec![elem.syntax_element()])
+pub fn insert(position: Position, elem: impl Into<SyntaxElement>) {
+    insert_all(position, vec![elem.into()])
 }
-pub fn insert_raw(position: Position, elem: impl Element) {
-    insert_all_raw(position, vec![elem.syntax_element()])
+pub fn insert_raw(position: Position, elem: impl Into<SyntaxElement>) {
+    insert_all_raw(position, vec![elem.into()])
 }
 pub fn insert_all(position: Position, mut elements: Vec<SyntaxElement>) {
     if let Some(first) = elements.first() {
@@ -100,17 +73,17 @@ pub fn insert_all_raw(position: Position, elements: Vec<SyntaxElement>) {
     parent.splice_children(index..index, elements);
 }
 
-pub fn remove(elem: impl Element) {
-    let elem = elem.syntax_element();
+pub fn remove(elem: impl Into<SyntaxElement>) {
+    let elem = elem.into();
     remove_all(elem.clone()..=elem)
 }
 pub fn remove_all(range: RangeInclusive<SyntaxElement>) {
     replace_all(range, Vec::new())
 }
 
-pub fn replace(old: impl Element, new: impl Element) {
-    let old = old.syntax_element();
-    replace_all(old.clone()..=old, vec![new.syntax_element()])
+pub fn replace(old: impl Into<SyntaxElement>, new: impl Into<SyntaxElement>) {
+    let old = old.into();
+    replace_all(old.clone()..=old, vec![new.into()])
 }
 pub fn replace_all(range: RangeInclusive<SyntaxElement>, new: Vec<SyntaxElement>) {
     let start = range.start().index();
@@ -119,11 +92,11 @@ pub fn replace_all(range: RangeInclusive<SyntaxElement>, new: Vec<SyntaxElement>
     parent.splice_children(start..end + 1, new)
 }
 
-pub fn append_child(node: &(impl Into<SyntaxNode> + Clone), child: impl Element) {
+pub fn append_child(node: impl Into<SyntaxNode>, child: impl Into<SyntaxElement>) {
     let position = Position::last_child_of(node);
     insert(position, child)
 }
-pub fn append_child_raw(node: &(impl Into<SyntaxNode> + Clone), child: impl Element) {
+pub fn append_child_raw(node: impl Into<SyntaxNode>, child: impl Into<SyntaxElement>) {
     let position = Position::last_child_of(node);
     insert_raw(position, child)
 }


Test patch:
diff --git a/crates/hir_def/src/nameres/tests/mod_resolution.rs b/crates/hir_def/src/nameres/tests/mod_resolution.rs
index 16a2cd27af..dfbbad1f90 100644
--- a/crates/hir_def/src/nameres/tests/mod_resolution.rs
+++ b/crates/hir_def/src/nameres/tests/mod_resolution.rs
@@ -819,22 +819,3 @@ pub mod hash { pub trait Hash {} }
         "#]],
     );
 }
-
-#[test]
-fn cfg_in_module_file() {
-    // Inner `#![cfg]` in a module file makes the whole module disappear.
-    check(
-        r#"
-//- /main.rs
-mod module;
-
-//- /module.rs
-#![cfg(NEVER)]
-
-struct AlsoShoulntAppear;
-        "#,
-        expect![[r#"
-            crate
-        "#]],
-    )
-}
diff --git a/crates/hir_ty/src/tests/traits.rs b/crates/hir_ty/src/tests/traits.rs
index 8f2bdffc03..8270fa2193 100644
--- a/crates/hir_ty/src/tests/traits.rs
+++ b/crates/hir_ty/src/tests/traits.rs
@@ -1412,8 +1412,8 @@ fn weird_bounds() {
             50..51 'b': impl
             69..70 'c': impl Trait
             86..87 'd': impl
-            107..108 'e': impl
-            123..124 'f': impl Trait
+            107..108 'e': impl {error}
+            123..124 'f': impl Trait + {error}
             147..149 '{}': ()
         "#]],
     );
diff --git a/crates/rust-analyzer/tests/rust-analyzer/main.rs b/crates/rust-analyzer/tests/rust-analyzer/main.rs
index 7545b4a348..19516de7b9 100644
--- a/crates/rust-analyzer/tests/rust-analyzer/main.rs
+++ b/crates/rust-analyzer/tests/rust-analyzer/main.rs
@@ -838,9 +838,7 @@ fn main() {}
                 new_uri: base_path.join("src/from_mod/foo.rs").to_str().unwrap().to_string(),
             }],
         },
-        json!({
-          "documentChanges": []
-        }),
+        json!(null),
     );
 
     //rename file from foo.rs to mod.rs
@@ -851,9 +849,7 @@ fn main() {}
                 new_uri: base_path.join("src/to_mod/mod.rs").to_str().unwrap().to_string(),
             }],
         },
-        json!({
-          "documentChanges": []
-        }),
+        json!(null),
     );
 
     //rename same level file