Repository: rust-analyzer/rust-analyzer
Pull request #7133 (2021-01-02 12:32:56)

Proper handling $crate and local_inner_macros
This PR introduces `HygineFrames` to store the macro definition/call site hierarchy in hyginee and when resolving `local_inner_macros` and `$crate`, we use the token to look up the corresponding frame and return the correct value.

See also: https://rustc-dev-guide.rust-lang.org/macro-expansion.html#hygiene-and-hierarchies

fixe #6890 and  #6788

r? @jonas-schievink 


Patch:
diff --git a/crates/assists/src/ast_transform.rs b/crates/assists/src/ast_transform.rs
index 4a3ed7783e..da94e9987c 100644
--- a/crates/assists/src/ast_transform.rs
+++ b/crates/assists/src/ast_transform.rs
@@ -204,8 +204,7 @@ impl<'a> AstTransform<'a> for QualifyPaths<'a> {
             }
             PathResolution::Local(_)
             | PathResolution::TypeParam(_)
-            | PathResolution::SelfType(_)
-            | PathResolution::ConstParam(_) => None,
+            | PathResolution::SelfType(_) => None,
             PathResolution::Macro(_) => None,
             PathResolution::AssocItem(_) => None,
         }
diff --git a/crates/base_db/src/input.rs b/crates/base_db/src/input.rs
index 2dd8fbe679..9567bcc424 100644
--- a/crates/base_db/src/input.rs
+++ b/crates/base_db/src/input.rs
@@ -190,11 +190,10 @@ pub struct CrateData {
     pub proc_macro: Vec<ProcMacro>,
 }
 
-#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 pub enum Edition {
-    Edition2015,
     Edition2018,
-    Edition2021,
+    Edition2015,
 }
 
 #[derive(Default, Debug, Clone, PartialEq, Eq)]
@@ -394,7 +393,6 @@ impl FromStr for Edition {
         let res = match s {
             "2015" => Edition::Edition2015,
             "2018" => Edition::Edition2018,
-            "2021" => Edition::Edition2021,
             _ => return Err(ParseEditionError { invalid_input: s.to_string() }),
         };
         Ok(res)
@@ -406,7 +404,6 @@ impl fmt::Display for Edition {
         f.write_str(match self {
             Edition::Edition2015 => "2015",
             Edition::Edition2018 => "2018",
-            Edition::Edition2021 => "2021",
         })
     }
 }
diff --git a/crates/hir/src/code_model.rs b/crates/hir/src/code_model.rs
index 97b7a8b5f5..b7ded34788 100644
--- a/crates/hir/src/code_model.rs
+++ b/crates/hir/src/code_model.rs
@@ -18,10 +18,10 @@ use hir_def::{
     resolver::{HasResolver, Resolver},
     src::HasSource as _,
     type_ref::{Mutability, TypeRef},
-    AdtId, AssocContainerId, AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId,
-    DefWithBodyId, EnumId, FunctionId, GenericDefId, HasModule, ImplId, LifetimeParamId,
-    LocalEnumVariantId, LocalFieldId, LocalModuleId, Lookup, ModuleId, StaticId, StructId, TraitId,
-    TypeAliasId, TypeParamId, UnionId,
+    AdtId, AssocContainerId, AssocItemId, AssocItemLoc, AttrDefId, ConstId, DefWithBodyId, EnumId,
+    FunctionId, GenericDefId, HasModule, ImplId, LifetimeParamId, LocalEnumVariantId, LocalFieldId,
+    LocalModuleId, Lookup, ModuleId, StaticId, StructId, TraitId, TypeAliasId, TypeParamId,
+    UnionId,
 };
 use hir_def::{find_path::PrefixKind, item_scope::ItemInNs, visibility::Visibility};
 use hir_expand::{
@@ -1125,12 +1125,7 @@ impl GenericDef {
                 id: LifetimeParamId { parent: self.into(), local_id },
             })
             .map(GenericParam::LifetimeParam);
-        let const_params = generics
-            .consts
-            .iter()
-            .map(|(local_id, _)| ConstParam { id: ConstParamId { parent: self.into(), local_id } })
-            .map(GenericParam::ConstParam);
-        ty_params.chain(lt_params).chain(const_params).collect()
+        ty_params.chain(lt_params).collect()
     }
 
     pub fn type_params(self, db: &dyn HirDatabase) -> Vec<TypeParam> {
@@ -1242,9 +1237,8 @@ impl Label {
 pub enum GenericParam {
     TypeParam(TypeParam),
     LifetimeParam(LifetimeParam),
-    ConstParam(ConstParam),
 }
-impl_from!(TypeParam, LifetimeParam, ConstParam for GenericParam);
+impl_from!(TypeParam, LifetimeParam for GenericParam);
 
 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
 pub struct TypeParam {
@@ -1306,26 +1300,6 @@ impl LifetimeParam {
     }
 }
 
-#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
-pub struct ConstParam {
-    pub(crate) id: ConstParamId,
-}
-
-impl ConstParam {
-    pub fn name(self, db: &dyn HirDatabase) -> Name {
-        let params = db.generic_params(self.id.parent);
-        params.consts[self.id.local_id].name.clone()
-    }
-
-    pub fn module(self, db: &dyn HirDatabase) -> Module {
-        self.id.parent.module(db.upcast()).into()
-    }
-
-    pub fn parent(self, _db: &dyn HirDatabase) -> GenericDef {
-        self.id.parent.into()
-    }
-}
-
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 pub struct Impl {
     pub(crate) id: ImplId,
diff --git a/crates/hir/src/from_id.rs b/crates/hir/src/from_id.rs
index 2422887e34..a0792b9a66 100644
--- a/crates/hir/src/from_id.rs
+++ b/crates/hir/src/from_id.rs
@@ -44,7 +44,6 @@ from_id![
     (hir_def::ImplId, crate::Impl),
     (hir_def::TypeParamId, crate::TypeParam),
     (hir_def::LifetimeParamId, crate::LifetimeParam),
-    (hir_def::ConstParamId, crate::ConstParam),
     (hir_expand::MacroDefId, crate::MacroDef)
 ];
 
diff --git a/crates/hir/src/has_source.rs b/crates/hir/src/has_source.rs
index dd7c0c5706..0dc07c33e2 100644
--- a/crates/hir/src/has_source.rs
+++ b/crates/hir/src/has_source.rs
@@ -10,8 +10,8 @@ use hir_expand::InFile;
 use syntax::ast;
 
 use crate::{
-    db::HirDatabase, Const, ConstParam, Enum, Field, FieldSource, Function, Impl, LifetimeParam,
-    MacroDef, Module, Static, Struct, Trait, TypeAlias, TypeParam, Union, Variant,
+    db::HirDatabase, Const, Enum, Field, FieldSource, Function, Impl, LifetimeParam, MacroDef,
+    Module, Static, Struct, Trait, TypeAlias, TypeParam, Union, Variant,
 };
 
 pub trait HasSource {
@@ -140,11 +140,3 @@ impl HasSource for LifetimeParam {
         child_source.map(|it| it[self.id.local_id].clone())
     }
 }
-
-impl HasSource for ConstParam {
-    type Ast = ast::ConstParam;
-    fn source(self, db: &dyn HirDatabase) -> InFile<Self::Ast> {
-        let child_source = self.id.parent.child_source(db.upcast());
-        child_source.map(|it| it[self.id.local_id].clone())
-    }
-}
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 8ac27e2dd8..7ac9fd5079 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -34,9 +34,9 @@ pub use crate::{
     attrs::{HasAttrs, Namespace},
     code_model::{
         Access, Adt, AsAssocItem, AssocItem, AssocItemContainer, Callable, CallableKind, Const,
-        ConstParam, Crate, CrateDependency, DefWithBody, Enum, Field, FieldSource, Function,
-        GenericDef, HasVisibility, Impl, Label, LifetimeParam, Local, MacroDef, Module, ModuleDef,
-        ScopeDef, Static, Struct, Trait, Type, TypeAlias, TypeParam, Union, Variant, VariantDef,
+        Crate, CrateDependency, DefWithBody, Enum, Field, FieldSource, Function, GenericDef,
+        HasVisibility, Impl, Label, LifetimeParam, Local, MacroDef, Module, ModuleDef, ScopeDef,
+        Static, Struct, Trait, Type, TypeAlias, TypeParam, Union, Variant, VariantDef,
     },
     has_source::HasSource,
     semantics::{PathResolution, Semantics, SemanticsScope},
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index cd689c8693..67cd16e311 100644
--- a/crates/hir/src/semantics.rs
+++ b/crates/hir/src/semantics.rs
@@ -25,9 +25,9 @@ use crate::{
     diagnostics::Diagnostic,
     semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx},
     source_analyzer::{resolve_hir_path, SourceAnalyzer},
-    AssocItem, Callable, ConstParam, Crate, Field, Function, HirFileId, Impl, InFile, Label,
-    LifetimeParam, Local, MacroDef, Module, ModuleDef, Name, Path, ScopeDef, Trait, Type,
-    TypeAlias, TypeParam, VariantDef,
+    AssocItem, Callable, Crate, Field, Function, HirFileId, Impl, InFile, Label, LifetimeParam,
+    Local, MacroDef, Module, ModuleDef, Name, Path, ScopeDef, Trait, Type, TypeAlias, TypeParam,
+    VariantDef,
 };
 
 #[derive(Debug, Clone, PartialEq, Eq)]
@@ -38,7 +38,6 @@ pub enum PathResolution {
     Local(Local),
     /// A generic parameter
     TypeParam(TypeParam),
-    ConstParam(ConstParam),
     SelfType(Impl),
     Macro(MacroDef),
     AssocItem(AssocItem),
@@ -60,9 +59,7 @@ impl PathResolution {
             PathResolution::Def(ModuleDef::TypeAlias(alias)) => {
                 Some(TypeNs::TypeAliasId((*alias).into()))
             }
-            PathResolution::Local(_) | PathResolution::Macro(_) | PathResolution::ConstParam(_) => {
-                None
-            }
+            PathResolution::Local(_) | PathResolution::Macro(_) => None,
             PathResolution::TypeParam(param) => Some(TypeNs::GenericParam((*param).into())),
             PathResolution::SelfType(impl_def) => Some(TypeNs::SelfType((*impl_def).into())),
             PathResolution::AssocItem(AssocItem::Const(_))
@@ -747,7 +744,6 @@ to_def_impls![
     (crate::Variant, ast::Variant, enum_variant_to_def),
     (crate::TypeParam, ast::TypeParam, type_param_to_def),
     (crate::LifetimeParam, ast::LifetimeParam, lifetime_param_to_def),
-    (crate::ConstParam, ast::ConstParam, const_param_to_def),
     (crate::MacroDef, ast::MacroRules, macro_rules_to_def),
     (crate::Local, ast::IdentPat, bind_pat_to_def),
     (crate::Label, ast::Label, label_to_def),
diff --git a/crates/hir/src/semantics/source_to_def.rs b/crates/hir/src/semantics/source_to_def.rs
index 4b9ebff729..424e6e8a94 100644
--- a/crates/hir/src/semantics/source_to_def.rs
+++ b/crates/hir/src/semantics/source_to_def.rs
@@ -6,9 +6,9 @@ use hir_def::{
     dyn_map::DynMap,
     expr::{LabelId, PatId},
     keys::{self, Key},
-    ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId, FieldId, FunctionId, GenericDefId,
-    ImplId, LifetimeParamId, ModuleId, StaticId, StructId, TraitId, TypeAliasId, TypeParamId,
-    UnionId, VariantId,
+    ConstId, DefWithBodyId, EnumId, EnumVariantId, FieldId, FunctionId, GenericDefId, ImplId,
+    LifetimeParamId, ModuleId, StaticId, StructId, TraitId, TypeAliasId, TypeParamId, UnionId,
+    VariantId,
 };
 use hir_expand::{name::AsName, AstId, MacroDefKind};
 use rustc_hash::FxHashMap;
@@ -157,18 +157,6 @@ impl SourceToDefCtx<'_, '_> {
         dyn_map[keys::LIFETIME_PARAM].get(&src).copied()
     }
 
-    pub(super) fn const_param_to_def(
-        &mut self,
-        src: InFile<ast::ConstParam>,
-    ) -> Option<ConstParamId> {
-        let container: ChildContainer =
-            self.find_generic_param_container(src.as_ref().map(|it| it.syntax()))?.into();
-        let db = self.db;
-        let dyn_map =
-            &*self.cache.entry(container).or_insert_with(|| container.child_by_source(db));
-        dyn_map[keys::CONST_PARAM].get(&src).copied()
-    }
-
     // FIXME: use DynMap as well?
     pub(super) fn macro_rules_to_def(
         &mut self,
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs
index 30a8e513dd..bddc49c05a 100644
--- a/crates/hir/src/source_analyzer.rs
+++ b/crates/hir/src/source_analyzer.rs
@@ -479,7 +479,6 @@ pub(crate) fn resolve_hir_path(
                 ValueNs::StructId(it) => PathResolution::Def(Struct::from(it).into()),
                 ValueNs::EnumVariantId(it) => PathResolution::Def(Variant::from(it).into()),
                 ValueNs::ImplSelf(impl_id) => PathResolution::SelfType(impl_id.into()),
-                ValueNs::GenericParam(it) => PathResolution::ConstParam(it.into()),
             };
             Some(res)
         });
diff --git a/crates/hir_def/src/generics.rs b/crates/hir_def/src/generics.rs
index 9b5b886c2b..bb8fca009a 100644
--- a/crates/hir_def/src/generics.rs
+++ b/crates/hir_def/src/generics.rs
@@ -21,11 +21,11 @@ use crate::{
     keys,
     src::{HasChildSource, HasSource},
     type_ref::{LifetimeRef, TypeBound, TypeRef},
-    AdtId, ConstParamId, GenericDefId, LifetimeParamId, LocalConstParamId, LocalLifetimeParamId,
-    LocalTypeParamId, Lookup, TypeParamId,
+    AdtId, GenericDefId, LifetimeParamId, LocalLifetimeParamId, LocalTypeParamId, Lookup,
+    TypeParamId,
 };
 
-/// Data about a generic type parameter (to a function, struct, impl, ...).
+/// Data about a generic parameter (to a function, struct, impl, ...).
 #[derive(Clone, PartialEq, Eq, Debug)]
 pub struct TypeParamData {
     pub name: Option<Name>,
@@ -33,19 +33,12 @@ pub struct TypeParamData {
     pub provenance: TypeParamProvenance,
 }
 
-/// Data about a generic lifetime parameter (to a function, struct, impl, ...).
+/// Data about a generic parameter (to a function, struct, impl, ...).
 #[derive(Clone, PartialEq, Eq, Debug)]
 pub struct LifetimeParamData {
     pub name: Name,
 }
 
-/// Data about a generic const parameter (to a function, struct, impl, ...).
-#[derive(Clone, PartialEq, Eq, Debug)]
-pub struct ConstParamData {
-    pub name: Name,
-    pub ty: TypeRef,
-}
-
 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
 pub enum TypeParamProvenance {
     TypeParamList,
@@ -58,7 +51,6 @@ pub enum TypeParamProvenance {
 pub struct GenericParams {
     pub types: Arena<TypeParamData>,
     pub lifetimes: Arena<LifetimeParamData>,
-    pub consts: Arena<ConstParamData>,
     pub where_predicates: Vec<WherePredicate>,
 }
 
@@ -84,7 +76,6 @@ pub enum WherePredicateTypeTarget {
 pub(crate) struct SourceMap {
     pub(crate) type_params: ArenaMap<LocalTypeParamId, Either<ast::Trait, ast::TypeParam>>,
     lifetime_params: ArenaMap<LocalLifetimeParamId, ast::LifetimeParam>,
-    const_params: ArenaMap<LocalConstParamId, ast::ConstParam>,
 }
 
 impl GenericParams {
@@ -277,13 +268,6 @@ impl GenericParams {
             let lifetime_ref = LifetimeRef::new_name(name);
             self.fill_bounds(&lower_ctx, &lifetime_param, Either::Right(lifetime_ref));
         }
-        for const_param in params.const_params() {
-            let name = const_param.name().map_or_else(Name::missing, |it| it.as_name());
-            let ty = const_param.ty().map_or(TypeRef::Error, |it| TypeRef::from_ast(lower_ctx, it));
-            let param = ConstParamData { name, ty };
-            let param_id = self.consts.alloc(param);
-            sm.const_params.insert(param_id, const_param.clone());
-        }
     }
 
     fn fill_where_predicates(&mut self, lower_ctx: &LowerCtx, where_clause: ast::WhereClause) {
@@ -369,16 +353,12 @@ impl GenericParams {
         });
     }
 
-    pub fn find_type_by_name(&self, name: &Name) -> Option<LocalTypeParamId> {
+    pub fn find_by_name(&self, name: &Name) -> Option<LocalTypeParamId> {
         self.types
             .iter()
             .find_map(|(id, p)| if p.name.as_ref() == Some(name) { Some(id) } else { None })
     }
 
-    pub fn find_const_by_name(&self, name: &Name) -> Option<LocalConstParamId> {
-        self.consts.iter().find_map(|(id, p)| if p.name == *name { Some(id) } else { None })
-    }
-
     pub fn find_trait_self_param(&self) -> Option<LocalTypeParamId> {
         self.types.iter().find_map(|(id, p)| {
             if p.provenance == TypeParamProvenance::TraitSelf {
@@ -410,16 +390,6 @@ impl HasChildSource<LocalLifetimeParamId> for GenericDefId {
     }
 }
 
-impl HasChildSource<LocalConstParamId> for GenericDefId {
-    type Value = ast::ConstParam;
-    fn child_source(
-        &self,
-        db: &dyn DefDatabase,
-    ) -> InFile<ArenaMap<LocalConstParamId, Self::Value>> {
-        GenericParams::new(db, *self).1.map(|source_maps| source_maps.const_params)
-    }
-}
-
 impl ChildBySource for GenericDefId {
     fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap {
         let mut res = DynMap::default();
@@ -436,10 +406,6 @@ impl ChildBySource for GenericDefId {
             let id = LifetimeParamId { parent: *self, local_id };
             res[keys::LIFETIME_PARAM].insert(sm.with_value(src.clone()), id);
         }
-        for (local_id, src) in sm.value.const_params.iter() {
-            let id = ConstParamId { parent: *self, local_id };
-            res[keys::CONST_PARAM].insert(sm.with_value(src.clone()), id);
-        }
         res
     }
 }
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs
index b6f5107313..100dbf5d65 100644
--- a/crates/hir_def/src/item_tree.rs
+++ b/crates/hir_def/src/item_tree.rs
@@ -260,7 +260,6 @@ impl GenericParamsStorage {
     fn alloc(&mut self, params: GenericParams) -> GenericParamsId {
         if params.types.is_empty()
             && params.lifetimes.is_empty()
-            && params.consts.is_empty()
             && params.where_predicates.is_empty()
         {
             return GenericParamsId::EMPTY;
@@ -270,12 +269,8 @@ impl GenericParamsStorage {
     }
 }
 
-static EMPTY_GENERICS: GenericParams = GenericParams {
-    types: Arena::new(),
-    lifetimes: Arena::new(),
-    consts: Arena::new(),
-    where_predicates: Vec::new(),
-};
+static EMPTY_GENERICS: GenericParams =
+    GenericParams { types: Arena::new(), lifetimes: Arena::new(), where_predicates: Vec::new() };
 
 #[derive(Default, Debug, Eq, PartialEq)]
 struct ItemTreeData {
diff --git a/crates/hir_def/src/keys.rs b/crates/hir_def/src/keys.rs
index 89b3ed8686..9c585de2ce 100644
--- a/crates/hir_def/src/keys.rs
+++ b/crates/hir_def/src/keys.rs
@@ -8,8 +8,8 @@ use syntax::{ast, AstNode, AstPtr};
 
 use crate::{
     dyn_map::{DynMap, Policy},
-    ConstId, ConstParamId, EnumId, EnumVariantId, FieldId, FunctionId, ImplId, LifetimeParamId,
-    StaticId, StructId, TraitId, TypeAliasId, TypeParamId, UnionId,
+    ConstId, EnumId, EnumVariantId, FieldId, FunctionId, ImplId, LifetimeParamId, StaticId,
+    StructId, TraitId, TypeAliasId, TypeParamId, UnionId,
 };
 
 pub type Key<K, V> = crate::dyn_map::Key<InFile<K>, V, AstPtrPolicy<K, V>>;
@@ -29,7 +29,6 @@ pub const TUPLE_FIELD: Key<ast::TupleField, FieldId> = Key::new();
 pub const RECORD_FIELD: Key<ast::RecordField, FieldId> = Key::new();
 pub const TYPE_PARAM: Key<ast::TypeParam, TypeParamId> = Key::new();
 pub const LIFETIME_PARAM: Key<ast::LifetimeParam, LifetimeParamId> = Key::new();
-pub const CONST_PARAM: Key<ast::ConstParam, ConstParamId> = Key::new();
 
 pub const MACRO: Key<ast::MacroCall, MacroDefId> = Key::new();
 
diff --git a/crates/hir_def/src/lib.rs b/crates/hir_def/src/lib.rs
index 25f460504f..ba09a9126b 100644
--- a/crates/hir_def/src/lib.rs
+++ b/crates/hir_def/src/lib.rs
@@ -231,13 +231,6 @@ pub struct LifetimeParamId {
 }
 pub type LocalLifetimeParamId = Idx<generics::LifetimeParamData>;
 
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-pub struct ConstParamId {
-    pub parent: GenericDefId,
-    pub local_id: LocalConstParamId,
-}
-pub type LocalConstParamId = Idx<generics::ConstParamData>;
-
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 pub enum ContainerId {
     ModuleId(ModuleId),
diff --git a/crates/hir_def/src/path/lower.rs b/crates/hir_def/src/path/lower.rs
index 8a01e6eead..9518ac109b 100644
--- a/crates/hir_def/src/path/lower.rs
+++ b/crates/hir_def/src/path/lower.rs
@@ -123,7 +123,7 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path>
     // We follow what it did anyway :)
     if segments.len() == 1 && kind == PathKind::Plain {
         if let Some(_macro_call) = path.syntax().parent().and_then(ast::MacroCall::cast) {
-            if let Some(crate_id) = hygiene.local_inner_macros() {
+            if let Some(crate_id) = hygiene.local_inner_macros(path) {
                 kind = PathKind::DollarCrate(crate_id);
             }
         }
diff --git a/crates/hir_def/src/resolver.rs b/crates/hir_def/src/resolver.rs
index 129f1dbac9..f8cc5e075e 100644
--- a/crates/hir_def/src/resolver.rs
+++ b/crates/hir_def/src/resolver.rs
@@ -20,9 +20,9 @@ use crate::{
     path::{ModPath, PathKind},
     per_ns::PerNs,
     visibility::{RawVisibility, Visibility},
-    AdtId, AssocContainerId, ConstId, ConstParamId, ContainerId, DefWithBodyId, EnumId,
-    EnumVariantId, FunctionId, GenericDefId, HasModule, ImplId, LocalModuleId, Lookup, ModuleDefId,
-    ModuleId, StaticId, StructId, TraitId, TypeAliasId, TypeParamId, VariantId,
+    AdtId, AssocContainerId, ConstId, ContainerId, DefWithBodyId, EnumId, EnumVariantId,
+    FunctionId, GenericDefId, HasModule, ImplId, LocalModuleId, Lookup, ModuleDefId, ModuleId,
+    StaticId, StructId, TraitId, TypeAliasId, TypeParamId, VariantId,
 };
 
 #[derive(Debug, Clone, Default)]
@@ -93,7 +93,6 @@ pub enum ValueNs {
     StaticId(StaticId),
     StructId(StructId),
     EnumVariantId(EnumVariantId),
-    GenericParam(ConstParamId),
 }
 
 impl Resolver {
@@ -164,7 +163,7 @@ impl Resolver {
                 }
 
                 Scope::GenericParams { params, def } => {
-                    if let Some(local_id) = params.find_type_by_name(first_name) {
+                    if let Some(local_id) = params.find_by_name(first_name) {
                         let idx = if path.segments.len() == 1 { None } else { Some(1) };
                         return Some((
                             TypeNs::GenericParam(TypeParamId { local_id, parent: *def }),
@@ -286,17 +285,11 @@ impl Resolver {
                 Scope::ExprScope(_) => continue,
 
                 Scope::GenericParams { params, def } if n_segments > 1 => {
-                    if let Some(local_id) = params.find_type_by_name(first_name) {
+                    if let Some(local_id) = params.find_by_name(first_name) {
                         let ty = TypeNs::GenericParam(TypeParamId { local_id, parent: *def });
                         return Some(ResolveValueResult::Partial(ty, 1));
                     }
                 }
-                Scope::GenericParams { params, def } if n_segments == 1 => {
-                    if let Some(local_id) = params.find_const_by_name(first_name) {
-                        let val = ValueNs::GenericParam(ConstParamId { local_id, parent: *def });
-                        return Some(ResolveValueResult::ValueNs(val));
-                    }
-                }
                 Scope::GenericParams { .. } => continue,
 
                 Scope::ImplDefScope(impl_) => {
diff --git a/crates/hir_expand/src/hygiene.rs b/crates/hir_expand/src/hygiene.rs
index 7ab0a5e52e..6042e15b22 100644
--- a/crates/hir_expand/src/hygiene.rs
+++ b/crates/hir_expand/src/hygiene.rs
@@ -2,30 +2,94 @@
 //!
 //! Specifically, `ast` + `Hygiene` allows you to create a `Name`. Note that, at
 //! this moment, this is horribly incomplete and handles only `$crate`.
+use std::sync::Arc;
+
+use arena::{Arena, Idx};
 use base_db::CrateId;
 use either::Either;
-use syntax::ast;
+use mbe::Origin;
+use syntax::{ast, AstNode};
 
 use crate::{
     db::AstDatabase,
     name::{AsName, Name},
-    HirFileId, HirFileIdRepr, MacroCallId, MacroDefKind,
+    ExpansionInfo, HirFileId, HirFileIdRepr, MacroCallId, MacroDefKind,
 };
 
 #[derive(Clone, Debug)]
 pub struct Hygiene {
-    // This is what `$crate` expands to
-    def_crate: Option<CrateId>,
+    frames: Option<Arc<HygieneFrames>>,
+}
+
+impl Hygiene {
+    pub fn new(db: &dyn AstDatabase, file_id: HirFileId) -> Hygiene {
+        Hygiene { frames: Some(Arc::new(HygieneFrames::new(db, file_id.clone()))) }
+    }
+
+    pub fn new_unhygienic() -> Hygiene {
+        Hygiene { frames: None }
+    }
+
+    // FIXME: this should just return name
+    pub fn name_ref_to_name(&self, name_ref: ast::NameRef) -> Either<Name, CrateId> {
+        if let Some(frames) = &self.frames {
+            if name_ref.text() == "$crate" {
+                if let Some(krate) = frames.root_crate(&name_ref) {
+                    return Either::Right(krate);
+                }
+            }
+        }
+
+        Either::Left(name_ref.as_name())
+    }
+
+    pub fn local_inner_macros(&self, path: ast::Path) -> Option<CrateId> {
+        let frames = self.frames.as_ref()?;
+
+        let mut token = path.syntax().first_token()?;
+        let mut current = frames.first();
+
+        while let Some((frame, data)) =
+            current.and_then(|it| Some((it, it.expansion.as_ref()?.map_token_up(&token)?)))
+        {
+            let (mapped, origin) = data;
+            if origin == Origin::Def {
+                return if frame.local_inner { frame.krate } else { None };
+            }
+            current = Some(&frames.0[frame.call_site?]);
+            token = mapped.value;
+        }
+        None
+    }
+}
+
+#[derive(Default, Debug)]
+struct HygieneFrames(Arena<HygieneFrame>);
+
+#[derive(Clone, Debug)]
+struct HygieneFrame {
+    expansion: Option<ExpansionInfo>,
 
     // Indicate this is a local inner macro
     local_inner: bool,
+    krate: Option<CrateId>,
+
+    call_site: Option<Idx<HygieneFrame>>,
+    def_site: Option<Idx<HygieneFrame>>,
 }
 
-impl Hygiene {
-    pub fn new(db: &dyn AstDatabase, file_id: HirFileId) -> Hygiene {
-        let (def_crate, local_inner) = match file_id.0 {
+impl HygieneFrames {
+    fn new(db: &dyn AstDatabase, file_id: HirFileId) -> Self {
+        let mut frames = HygieneFrames::default();
+        frames.add(db, file_id);
+        frames
+    }
+
+    fn add(&mut self, db: &dyn AstDatabase, file_id: HirFileId) -> Option<Idx<HygieneFrame>> {
+        let (krate, local_inner) = match file_id.0 {
             HirFileIdRepr::FileId(_) => (None, false),
             HirFileIdRepr::MacroFile(macro_file) => match macro_file.macro_call_id {
+                MacroCallId::EagerMacro(_id) => (None, false),
                 MacroCallId::LazyMacro(id) => {
                     let loc = db.lookup_intern_macro(id);
                     match loc.def.kind {
@@ -36,31 +100,68 @@ impl Hygiene {
                         MacroDefKind::ProcMacro(_) => (None, false),
                     }
                 }
-                MacroCallId::EagerMacro(_id) => (None, false),
             },
         };
-        Hygiene { def_crate, local_inner }
-    }
 
-    pub fn new_unhygienic() -> Hygiene {
-        Hygiene { def_crate: None, local_inner: false }
+        let expansion = file_id.expansion_info(db);
+        let expansion = match expansion {
+            None => {
+                return Some(self.0.alloc(HygieneFrame {
+                    expansion: None,
+                    local_inner,
+                    krate,
+                    call_site: None,
+                    def_site: None,
+                }));
+            }
+            Some(it) => it,
+        };
+
+        let def_site = expansion.def.clone();
+        let call_site = expansion.arg.file_id;
+        let idx = self.0.alloc(HygieneFrame {
+            expansion: Some(expansion),
+            local_inner,
+            krate,
+            call_site: None,
+            def_site: None,
+        });
+
+        self.0[idx].call_site = self.add(db, call_site);
+        self.0[idx].def_site = def_site.and_then(|it| self.add(db, it.file_id));
+
+        Some(idx)
     }
 
-    // FIXME: this should just return name
-    pub fn name_ref_to_name(&self, name_ref: ast::NameRef) -> Either<Name, CrateId> {
-        if let Some(def_crate) = self.def_crate {
-            if name_ref.text() == "$crate" {
-                return Either::Right(def_crate);
-            }
-        }
-        Either::Left(name_ref.as_name())
+    fn first(&self) -> Option<&HygieneFrame> {
+        self.0.iter().next().map(|it| it.1)
     }
 
-    pub fn local_inner_macros(&self) -> Option<CrateId> {
-        if self.local_inner {
-            self.def_crate
-        } else {
-            None
+    fn root_crate(&self, name_ref: &ast::NameRef) -> Option<CrateId> {
+        let mut token = name_ref.syntax().first_token()?;
+        let first = self.first()?;
+        let mut result = first.krate;
+        let mut current = Some(first);
+
+        while let Some((frame, (mapped, origin))) =
+            current.and_then(|it| Some((it, it.expansion.as_ref()?.map_token_up(&token)?)))
+        {
+            result = frame.krate;
+
+            let site = match origin {
+                Origin::Def => frame.def_site,
+                Origin::Call => frame.call_site,
+            };
+
+            let site = match site {
+                None => break,
+                Some(it) => it,
+            };
+
+            current = Some(&self.0[site]);
+            token = mapped.value;
         }
+
+        result
     }
 }
diff --git a/crates/hir_expand/src/lib.rs b/crates/hir_expand/src/lib.rs
index 3fa1b1d776..5b6734a5f4 100644
--- a/crates/hir_expand/src/lib.rs
+++ b/crates/hir_expand/src/lib.rs
@@ -340,11 +340,8 @@ impl ExpansionInfo {
         Some(self.expanded.with_value(token))
     }
 
-    pub fn map_token_up(
-        &self,
-        token: InFile<&SyntaxToken>,
-    ) -> Option<(InFile<SyntaxToken>, Origin)> {
-        let token_id = self.exp_map.token_by_range(token.value.text_range())?;
+    pub fn map_token_up(&self, token: &SyntaxToken) -> Option<(InFile<SyntaxToken>, Origin)> {
+        let token_id = self.exp_map.token_by_range(token.text_range())?;
 
         let (token_id, origin) = self.macro_def.0.map_id_up(token_id);
         let (token_map, tt) = match origin {
@@ -359,7 +356,7 @@ impl ExpansionInfo {
             ),
         };
 
-        let range = token_map.range_by_token(token_id)?.by_kind(token.value.kind())?;
+        let range = token_map.range_by_token(token_id)?.by_kind(token.kind())?;
         let token = algo::find_covering_element(&tt.value, range + tt.value.text_range().start())
             .into_token()?;
         Some((tt.with_value(token), origin))
@@ -495,7 +492,7 @@ fn ascend_call_token(
     expansion: &ExpansionInfo,
     token: InFile<SyntaxToken>,
 ) -> Option<InFile<SyntaxToken>> {
-    let (mapped, origin) = expansion.map_token_up(token.as_ref())?;
+    let (mapped, origin) = expansion.map_token_up(&token.value)?;
     if origin != Origin::Call {
         return None;
     }
diff --git a/crates/hir_ty/src/db.rs b/crates/hir_ty/src/db.rs
index f3567c49e6..66bdb8e88e 100644
--- a/crates/hir_ty/src/db.rs
+++ b/crates/hir_ty/src/db.rs
@@ -5,8 +5,8 @@ use std::sync::Arc;
 use arena::map::ArenaMap;
 use base_db::{impl_intern_key, salsa, CrateId, Upcast};
 use hir_def::{
-    db::DefDatabase, expr::ExprId, ConstParamId, DefWithBodyId, FunctionId, GenericDefId, ImplId,
-    LocalFieldId, TypeParamId, VariantId,
+    db::DefDatabase, expr::ExprId, DefWithBodyId, FunctionId, GenericDefId, ImplId, LocalFieldId,
+    TypeParamId, VariantId,
 };
 
 use crate::{
@@ -37,9 +37,6 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
     #[salsa::cycle(crate::lower::impl_self_ty_recover)]
     fn impl_self_ty(&self, def: ImplId) -> Binders<Ty>;
 
-    #[salsa::invoke(crate::lower::const_param_ty_query)]
-    fn const_param_ty(&self, def: ConstParamId) -> Ty;
-
     #[salsa::invoke(crate::lower::impl_trait_query)]
     fn impl_trait(&self, def: ImplId) -> Option<Binders<TraitRef>>;
 
diff --git a/crates/hir_ty/src/diagnostics/expr.rs b/crates/hir_ty/src/diagnostics/expr.rs
index b4e453411a..8494157063 100644
--- a/crates/hir_ty/src/diagnostics/expr.rs
+++ b/crates/hir_ty/src/diagnostics/expr.rs
@@ -156,7 +156,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
         // FIXME: Due to shortcomings in the current type system implementation, only emit this
         // diagnostic if there are no type mismatches in the containing function.
         if self.infer.type_mismatches.iter().next().is_some() {
-            return None;
+            return Some(());
         }
 
         let is_method_call = matches!(expr, Expr::MethodCall { .. });
@@ -170,14 +170,6 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
                 let mut args = args.clone();
                 args.insert(0, *receiver);
 
-                let receiver = &self.infer.type_of_expr[*receiver];
-                if receiver.strip_references().is_unknown() {
-                    // if the receiver is of unknown type, it's very likely we
-                    // don't know enough to correctly resolve the method call.
-                    // This is kind of a band-aid for #6975.
-                    return None;
-                }
-
                 // FIXME: note that we erase information about substs here. This
                 // is not right, but, luckily, doesn't matter as we care only
                 // about the number of params
@@ -512,22 +504,6 @@ fn f() {
         );
     }
 
-    #[test]
-    fn method_unknown_receiver() {
-        // note: this is incorrect code, so there might be errors on this in the
-        // future, but we shouldn't emit an argument count diagnostic here
-        check_diagnostics(
-            r#"
-trait Foo { fn method(&self, arg: usize) {} }
-
-fn f() {
-    let x;
-    x.method();
-}
-"#,
-        );
-    }
-
     #[test]
     fn tuple_struct() {
         check_diagnostics(
diff --git a/crates/hir_ty/src/infer/path.rs b/crates/hir_ty/src/infer/path.rs
index 5d541104e2..80d7ed10ec 100644
--- a/crates/hir_ty/src/infer/path.rs
+++ b/crates/hir_ty/src/infer/path.rs
@@ -89,7 +89,6 @@ impl<'a> InferenceContext<'a> {
                     return None;
                 }
             }
-            ValueNs::GenericParam(it) => return Some(self.db.const_param_ty(it)),
         };
 
         let ty = self.db.value_ty(typable);
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs
index e00c7e1766..357bd92f99 100644
--- a/crates/hir_ty/src/lib.rs
+++ b/crates/hir_ty/src/lib.rs
@@ -791,10 +791,6 @@ impl Ty {
         matches!(self, Ty::Apply(ApplicationTy { ctor: TypeCtor::Never, .. }))
     }
 
-    pub fn is_unknown(&self) -> bool {
-        matches!(self, Ty::Unknown)
-    }
-
     /// If this is a `dyn Trait` type, this returns the `Trait` part.
     pub fn dyn_trait_ref(&self) -> Option<&TraitRef> {
         match self {
diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs
index 222f61a11d..8da56cd11c 100644
--- a/crates/hir_ty/src/lower.rs
+++ b/crates/hir_ty/src/lower.rs
@@ -16,9 +16,9 @@ use hir_def::{
     path::{GenericArg, Path, PathSegment, PathSegments},
     resolver::{HasResolver, Resolver, TypeNs},
     type_ref::{TypeBound, TypeRef},
-    AdtId, AssocContainerId, AssocItemId, ConstId, ConstParamId, EnumId, EnumVariantId, FunctionId,
-    GenericDefId, HasModule, ImplId, LocalFieldId, Lookup, StaticId, StructId, TraitId,
-    TypeAliasId, TypeParamId, UnionId, VariantId,
+    AdtId, AssocContainerId, AssocItemId, ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId,
+    HasModule, ImplId, LocalFieldId, Lookup, StaticId, StructId, TraitId, TypeAliasId, TypeParamId,
+    UnionId, VariantId,
 };
 use hir_expand::name::Name;
 use smallvec::SmallVec;
@@ -1221,15 +1221,6 @@ pub(crate) fn impl_self_ty_query(db: &dyn HirDatabase, impl_id: ImplId) -> Binde
     Binders::new(generics.len(), Ty::from_hir(&ctx, &impl_data.target_type))
 }
 
-pub(crate) fn const_param_ty_query(db: &dyn HirDatabase, def: ConstParamId) -> Ty {
-    let parent_data = db.generic_params(def.parent);
-    let data = &parent_data.consts[def.local_id];
-    let resolver = def.parent.resolver(db.upcast());
-    let ctx = TyLoweringContext::new(db, &resolver);
-
-    Ty::from_hir(&ctx, &data.ty)
-}
-
 pub(crate) fn impl_self_ty_recover(
     db: &dyn HirDatabase,
     _cycle: &[String],
diff --git a/crates/ide/src/display/navigation_target.rs b/crates/ide/src/display/navigation_target.rs
index bcde2b6f12..6431e7d6db 100644
--- a/crates/ide/src/display/navigation_target.rs
+++ b/crates/ide/src/display/navigation_target.rs
@@ -24,7 +24,6 @@ pub enum SymbolKind {
     Impl,
     Field,
     TypeParam,
-    ConstParam,
     LifetimeParam,
     ValueParam,
     SelfParam,
@@ -226,7 +225,6 @@ impl TryToNav for Definition {
             Definition::TypeParam(it) => Some(it.to_nav(db)),
             Definition::LifetimeParam(it) => Some(it.to_nav(db)),
             Definition::Label(it) => Some(it.to_nav(db)),
-            Definition::ConstParam(it) => Some(it.to_nav(db)),
         }
     }
 }
@@ -487,23 +485,6 @@ impl ToNav for hir::LifetimeParam {
     }
 }
 
-impl ToNav for hir::ConstParam {
-    fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
-        let src = self.source(db);
-        let full_range = src.value.syntax().text_range();
-        NavigationTarget {
-            file_id: src.file_id.original_file(db),
-            name: self.name(db).to_string().into(),
-            kind: Some(SymbolKind::ConstParam),
-            full_range,
-            focus_range: src.value.name().map(|n| n.syntax().text_range()),
-            container_name: None,
-            description: None,
-            docs: None,
-        }
-    }
-}
-
 /// Get a description of a symbol.
 ///
 /// e.g. `struct Name`, `enum Name`, `fn Name`
diff --git a/crates/ide/src/doc_links.rs b/crates/ide/src/doc_links.rs
index 367fac05e9..e10516f43a 100644
--- a/crates/ide/src/doc_links.rs
+++ b/crates/ide/src/doc_links.rs
@@ -193,7 +193,6 @@ fn rewrite_intra_doc_link(
         Definition::SelfType(_)
         | Definition::Local(_)
         | Definition::TypeParam(_)
-        | Definition::ConstParam(_)
         | Definition::LifetimeParam(_)
         | Definition::Label(_) => return None,
     }?;
diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs
index 98c7bfbe51..73245fbe75 100644
--- a/crates/ide/src/hover.rs
+++ b/crates/ide/src/hover.rs
@@ -109,8 +109,6 @@ pub(crate) fn hover(
         match node {
             ast::Name(name) => NameClass::classify(&sema, &name).and_then(|d| d.defined(sema.db)),
             ast::NameRef(name_ref) => NameRefClass::classify(&sema, &name_ref).map(|d| d.referenced(sema.db)),
-            ast::Lifetime(lifetime) => NameClass::classify_lifetime(&sema, &lifetime)
-                .map_or_else(|| NameRefClass::classify_lifetime(&sema, &lifetime).map(|d| d.referenced(sema.db)), |d| d.defined(sema.db)),
             _ => None,
         }
     };
@@ -362,9 +360,9 @@ fn hover_for_definition(db: &RootDatabase, def: Definition) -> Option<Markup> {
             ModuleDef::Static(it) => from_def_source(db, it, mod_path),
             ModuleDef::Trait(it) => from_def_source(db, it, mod_path),
             ModuleDef::TypeAlias(it) => from_def_source(db, it, mod_path),
-            ModuleDef::BuiltinType(it) => Some(Markup::fenced_block(&it)),
+            ModuleDef::BuiltinType(it) => return Some(it.to_string().into()),
         },
-        Definition::Local(it) => Some(Markup::fenced_block(&it.ty(db).display(db))),
+        Definition::Local(it) => return Some(Markup::fenced_block(&it.ty(db).display(db))),
         Definition::SelfType(impl_def) => {
             impl_def.target_ty(db).as_adt().and_then(|adt| match adt {
                 Adt::Struct(it) => from_def_source(db, it, mod_path),
@@ -372,9 +370,7 @@ fn hover_for_definition(db: &RootDatabase, def: Definition) -> Option<Markup> {
                 Adt::Enum(it) => from_def_source(db, it, mod_path),
             })
         }
-        Definition::Label(it) => Some(Markup::fenced_block(&it.name(db))),
-        Definition::LifetimeParam(it) => Some(Markup::fenced_block(&it.name(db))),
-        Definition::TypeParam(_) | Definition::ConstParam(_) => {
+        Definition::TypeParam(_) | Definition::LifetimeParam(_) | Definition::Label(_) => {
             // FIXME: Hover for generic param
             None
         }
@@ -407,7 +403,7 @@ fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> {
     return tokens.max_by_key(priority);
     fn priority(n: &SyntaxToken) -> usize {
         match n.kind() {
-            IDENT | INT_NUMBER | LIFETIME_IDENT => 3,
+            IDENT | INT_NUMBER => 3,
             T!['('] | T![')'] => 2,
             kind if kind.is_trivia() => 0,
             _ => 1,
@@ -1173,10 +1169,7 @@ fn f() { fo<|>o!(); }
             r#"struct TS(String, i32<|>);"#,
             expect![[r#"
                 *i32*
-
-                ```rust
                 i32
-                ```
             "#]],
         )
     }
@@ -3228,36 +3221,4 @@ fn no_hover() {
 "#,
         );
     }
-
-    #[test]
-    fn hover_label() {
-        check(
-            r#"
-fn foo() {
-    'label<|>: loop {}
-}
-"#,
-            expect![[r#"
-            *'label*
-
-            ```rust
-            'label
-            ```
-            "#]],
-        );
-    }
-
-    #[test]
-    fn hover_lifetime() {
-        check(
-            r#"fn foo<'lifetime>(_: &'lifetime<|> ()) {}"#,
-            expect![[r#"
-            *'lifetime*
-
-            ```rust
-            'lifetime
-            ```
-            "#]],
-        );
-    }
 }
diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs
index fa58fc3196..21b2d7ca1c 100644
--- a/crates/ide/src/references.rs
+++ b/crates/ide/src/references.rs
@@ -1144,20 +1144,4 @@ fn foo<'a>() -> &'a () {
             "#]],
         );
     }
-
-    #[test]
-    fn test_find_const_param() {
-        check(
-            r#"
-fn foo<const FOO<|>: usize>() -> usize {
-    FOO
-}
-"#,
-            expect![[r#"
-                FOO ConstParam FileId(0) 7..23 13..16 Other
-
-                FileId(0) 42..45 Other
-            "#]],
-        );
-    }
 }
diff --git a/crates/ide/src/runnables.rs b/crates/ide/src/runnables.rs
index c893afc7cf..8911832660 100644
--- a/crates/ide/src/runnables.rs
+++ b/crates/ide/src/runnables.rs
@@ -230,7 +230,7 @@ impl TestAttr {
 
 const RUSTDOC_FENCE: &str = "```";
 const RUSTDOC_CODE_BLOCK_ATTRIBUTES_RUNNABLE: &[&str] =
-    &["", "rust", "should_panic", "edition2015", "edition2018", "edition2021"];
+    &["", "rust", "should_panic", "edition2015", "edition2018"];
 
 fn has_runnable_doc_test(attrs: &hir::Attrs) -> bool {
     attrs.docs().map_or(false, |doc| {
diff --git a/crates/ide/src/syntax_highlighting.rs b/crates/ide/src/syntax_highlighting.rs
index ba00852445..5ad96581bd 100644
--- a/crates/ide/src/syntax_highlighting.rs
+++ b/crates/ide/src/syntax_highlighting.rs
@@ -819,7 +819,6 @@ fn highlight_def(db: &RootDatabase, def: Definition) -> Highlight {
         },
         Definition::SelfType(_) => HighlightTag::Symbol(SymbolKind::Impl),
         Definition::TypeParam(_) => HighlightTag::Symbol(SymbolKind::TypeParam),
-        Definition::ConstParam(_) => HighlightTag::Symbol(SymbolKind::ConstParam),
         Definition::Local(local) => {
             let tag = if local.is_param(db) {
                 HighlightTag::Symbol(SymbolKind::ValueParam)
diff --git a/crates/ide/src/syntax_highlighting/injection.rs b/crates/ide/src/syntax_highlighting/injection.rs
index 6cbd683c69..9eb184c74b 100644
--- a/crates/ide/src/syntax_highlighting/injection.rs
+++ b/crates/ide/src/syntax_highlighting/injection.rs
@@ -54,17 +54,8 @@ pub(super) fn highlight_injection(
 type RangesMap = BTreeMap<TextSize, TextSize>;
 
 const RUSTDOC_FENCE: &'static str = "```";
-const RUSTDOC_FENCE_TOKENS: &[&'static str] = &[
-    "",
-    "rust",
-    "should_panic",
-    "ignore",
-    "no_run",
-    "compile_fail",
-    "edition2015",
-    "edition2018",
-    "edition2021",
-];
+const RUSTDOC_FENCE_TOKENS: &[&'static str] =
+    &["", "rust", "should_panic", "ignore", "no_run", "compile_fail", "edition2015", "edition2018"];
 
 /// Extracts Rust code from documentation comments as well as a mapping from
 /// the extracted source code back to the original source ranges.
diff --git a/crates/ide/src/syntax_highlighting/tags.rs b/crates/ide/src/syntax_highlighting/tags.rs
index 8b88670798..2a6cc0cab6 100644
--- a/crates/ide/src/syntax_highlighting/tags.rs
+++ b/crates/ide/src/syntax_highlighting/tags.rs
@@ -77,7 +77,6 @@ impl HighlightTag {
                 SymbolKind::Function => "function",
                 SymbolKind::TypeAlias => "type_alias",
                 SymbolKind::TypeParam => "type_param",
-                SymbolKind::ConstParam => "const_param",
                 SymbolKind::LifetimeParam => "lifetime",
                 SymbolKind::Macro => "macro",
                 SymbolKind::Local => "variable",
diff --git a/crates/ide_db/src/defs.rs b/crates/ide_db/src/defs.rs
index cc5078bf0f..d33a6cb863 100644
--- a/crates/ide_db/src/defs.rs
+++ b/crates/ide_db/src/defs.rs
@@ -6,8 +6,8 @@
 // FIXME: this badly needs rename/rewrite (matklad, 2020-02-06).
 
 use hir::{
-    db::HirDatabase, ConstParam, Crate, Field, HasVisibility, Impl, Label, LifetimeParam, Local,
-    MacroDef, Module, ModuleDef, Name, PathResolution, Semantics, TypeParam, Visibility,
+    db::HirDatabase, Crate, Field, HasVisibility, Impl, Label, LifetimeParam, Local, MacroDef,
+    Module, ModuleDef, Name, PathResolution, Semantics, TypeParam, Visibility,
 };
 use syntax::{
     ast::{self, AstNode},
@@ -26,7 +26,6 @@ pub enum Definition {
     Local(Local),
     TypeParam(TypeParam),
     LifetimeParam(LifetimeParam),
-    ConstParam(ConstParam),
     Label(Label),
 }
 
@@ -40,7 +39,6 @@ impl Definition {
             Definition::Local(it) => Some(it.module(db)),
             Definition::TypeParam(it) => Some(it.module(db)),
             Definition::LifetimeParam(it) => Some(it.module(db)),
-            Definition::ConstParam(it) => Some(it.module(db)),
             Definition::Label(it) => Some(it.module(db)),
         }
     }
@@ -54,7 +52,6 @@ impl Definition {
             Definition::Local(_) => None,
             Definition::TypeParam(_) => None,
             Definition::LifetimeParam(_) => None,
-            Definition::ConstParam(_) => None,
             Definition::Label(_) => None,
         }
     }
@@ -82,7 +79,6 @@ impl Definition {
             Definition::Local(it) => it.name(db)?,
             Definition::TypeParam(it) => it.name(db),
             Definition::LifetimeParam(it) => it.name(db),
-            Definition::ConstParam(it) => it.name(db),
             Definition::Label(it) => it.name(db),
         };
         Some(name)
@@ -237,10 +233,6 @@ impl NameClass {
                     let def = sema.to_def(&it)?;
                     Some(NameClass::Definition(Definition::TypeParam(def)))
                 },
-                ast::ConstParam(it) => {
-                    let def = sema.to_def(&it)?;
-                    Some(NameClass::Definition(Definition::ConstParam(def)))
-                },
                 _ => None,
             }
         }
@@ -425,7 +417,6 @@ impl From<PathResolution> for Definition {
             PathResolution::TypeParam(par) => Definition::TypeParam(par),
             PathResolution::Macro(def) => Definition::Macro(def),
             PathResolution::SelfType(impl_def) => Definition::SelfType(impl_def),
-            PathResolution::ConstParam(par) => Definition::ConstParam(par),
         }
     }
 }
diff --git a/crates/mbe/src/mbe_expander/matcher.rs b/crates/mbe/src/mbe_expander/matcher.rs
index ab5f87c487..385b466018 100644
--- a/crates/mbe/src/mbe_expander/matcher.rs
+++ b/crates/mbe/src/mbe_expander/matcher.rs
@@ -150,7 +150,7 @@ fn match_subtree(
                     res.add_err(err!("leftover tokens"));
                 }
             }
-            Op::Var { name, kind } => {
+            Op::Var { name, kind, .. } => {
                 let kind = match kind {
                     Some(k) => k,
                     None => {
diff --git a/crates/mbe/src/mbe_expander/transcriber.rs b/crates/mbe/src/mbe_expander/transcriber.rs
index 7205312371..57f3f104dc 100644
--- a/crates/mbe/src/mbe_expander/transcriber.rs
+++ b/crates/mbe/src/mbe_expander/transcriber.rs
@@ -100,8 +100,8 @@ fn expand_subtree(
                 err = err.or(e);
                 arena.push(tt.into());
             }
-            Op::Var { name, .. } => {
-                let ExpandResult { value: fragment, err: e } = expand_var(ctx, &name);
+            Op::Var { name, id, .. } => {
+                let ExpandResult { value: fragment, err: e } = expand_var(ctx, &name, *id);
                 err = err.or(e);
                 push_fragment(arena, fragment);
             }
@@ -118,12 +118,10 @@ fn expand_subtree(
     ExpandResult { value: tt::Subtree { delimiter: template.delimiter, token_trees: tts }, err }
 }
 
-fn expand_var(ctx: &mut ExpandCtx, v: &SmolStr) -> ExpandResult<Fragment> {
+fn expand_var(ctx: &mut ExpandCtx, v: &SmolStr, id: tt::TokenId) -> ExpandResult<Fragment> {
     if v == "crate" {
         // We simply produce identifier `$crate` here. And it will be resolved when lowering ast to Path.
-        let tt =
-            tt::Leaf::from(tt::Ident { text: "$crate".into(), id: tt::TokenId::unspecified() })
-                .into();
+        let tt = tt::Leaf::from(tt::Ident { text: "$crate".into(), id }).into();
         ExpandResult::ok(Fragment::Tokens(tt))
     } else if !ctx.bindings.contains(v) {
         // Note that it is possible to have a `$var` inside a macro which is not bound.
@@ -142,14 +140,8 @@ fn expand_var(ctx: &mut ExpandCtx, v: &SmolStr) -> ExpandResult<Fragment> {
         let tt = tt::Subtree {
             delimiter: None,
             token_trees: vec![
-                tt::Leaf::from(tt::Punct {
-                    char: '$',
-                    spacing: tt::Spacing::Alone,
-                    id: tt::TokenId::unspecified(),
-                })
-                .into(),
-                tt::Leaf::from(tt::Ident { text: v.clone(), id: tt::TokenId::unspecified() })
-                    .into(),
+                tt::Leaf::from(tt::Punct { char: '$', spacing: tt::Spacing::Alone, id }).into(),
+                tt::Leaf::from(tt::Ident { text: v.clone(), id }).into(),
             ],
         }
         .into();
diff --git a/crates/mbe/src/parser.rs b/crates/mbe/src/parser.rs
index 2f3ebc8313..77cc739b65 100644
--- a/crates/mbe/src/parser.rs
+++ b/crates/mbe/src/parser.rs
@@ -8,7 +8,7 @@ use crate::{tt_iter::TtIter, ExpandError, MetaTemplate};
 
 #[derive(Clone, Debug, PartialEq, Eq)]
 pub(crate) enum Op {
-    Var { name: SmolStr, kind: Option<SmolStr> },
+    Var { name: SmolStr, kind: Option<SmolStr>, id: tt::TokenId },
     Repeat { subtree: MetaTemplate, kind: RepeatKind, separator: Option<Separator> },
     Leaf(tt::Leaf),
     Subtree(MetaTemplate),
@@ -106,18 +106,21 @@ fn next_op<'a>(first: &tt::TokenTree, src: &mut TtIter<'a>, mode: Mode) -> Resul
                         }
                         let name = UNDERSCORE.clone();
                         let kind = eat_fragment_kind(src, mode)?;
-                        Op::Var { name, kind }
+                        let id = punct.id;
+                        Op::Var { name, kind, id }
                     }
                     tt::Leaf::Ident(ident) => {
                         let name = ident.text.clone();
                         let kind = eat_fragment_kind(src, mode)?;
-                        Op::Var { name, kind }
+                        let id = ident.id;
+                        Op::Var { name, kind, id }
                     }
                     tt::Leaf::Literal(lit) => {
                         if is_boolean_literal(&lit) {
                             let name = lit.text.clone();
                             let kind = eat_fragment_kind(src, mode)?;
-                            Op::Var { name, kind }
+                            let id = lit.id;
+                            Op::Var { name, kind, id }
                         } else {
                             bail!("bad var 2");
                         }
diff --git a/crates/project_model/src/project_json.rs b/crates/project_model/src/project_json.rs
index af884eb84a..aab279223a 100644
--- a/crates/project_model/src/project_json.rs
+++ b/crates/project_model/src/project_json.rs
@@ -139,8 +139,6 @@ enum EditionData {
     Edition2015,
     #[serde(rename = "2018")]
     Edition2018,
-    #[serde(rename = "2021")]
-    Edition2021,
 }
 
 impl From<EditionData> for Edition {
@@ -148,7 +146,6 @@ impl From<EditionData> for Edition {
         match data {
             EditionData::Edition2015 => Edition::Edition2015,
             EditionData::Edition2018 => Edition::Edition2018,
-            EditionData::Edition2021 => Edition::Edition2021,
         }
     }
 }
diff --git a/crates/rust-analyzer/src/markdown.rs b/crates/rust-analyzer/src/markdown.rs
index a49a58c000..968ea55f0c 100644
--- a/crates/rust-analyzer/src/markdown.rs
+++ b/crates/rust-analyzer/src/markdown.rs
@@ -1,17 +1,8 @@
 //! Transforms markdown
 
 const RUSTDOC_FENCE: &str = "```";
-const RUSTDOC_CODE_BLOCK_ATTRIBUTES_RUST_SPECIFIC: &[&str] = &[
-    "",
-    "rust",
-    "should_panic",
-    "ignore",
-    "no_run",
-    "compile_fail",
-    "edition2015",
-    "edition2018",
-    "edition2021",
-];
+const RUSTDOC_CODE_BLOCK_ATTRIBUTES_RUST_SPECIFIC: &[&str] =
+    &["", "rust", "should_panic", "ignore", "no_run", "compile_fail", "edition2015", "edition2018"];
 
 pub(crate) fn format_docs(src: &str) -> String {
     let mut processed_lines = Vec::new();
diff --git a/crates/rust-analyzer/src/semantic_tokens.rs b/crates/rust-analyzer/src/semantic_tokens.rs
index 5c4366f16e..c2f6a655d4 100644
--- a/crates/rust-analyzer/src/semantic_tokens.rs
+++ b/crates/rust-analyzer/src/semantic_tokens.rs
@@ -44,7 +44,6 @@ define_semantic_token_types![
     (ESCAPE_SEQUENCE, "escapeSequence"),
     (FORMAT_SPECIFIER, "formatSpecifier"),
     (GENERIC, "generic"),
-    (CONST_PARAMETER, "constParameter"),
     (LIFETIME, "lifetime"),
     (LABEL, "label"),
     (PUNCTUATION, "punctuation"),
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs
index 999b183515..1a38e79f08 100644
--- a/crates/rust-analyzer/src/to_proto.rs
+++ b/crates/rust-analyzer/src/to_proto.rs
@@ -42,7 +42,6 @@ pub(crate) fn symbol_kind(symbol_kind: SymbolKind) -> lsp_types::SymbolKind {
         SymbolKind::Field => lsp_types::SymbolKind::Field,
         SymbolKind::Static => lsp_types::SymbolKind::Constant,
         SymbolKind::Const => lsp_types::SymbolKind::Constant,
-        SymbolKind::ConstParam => lsp_types::SymbolKind::Constant,
         SymbolKind::Impl => lsp_types::SymbolKind::Object,
         SymbolKind::Local
         | SymbolKind::SelfParam
@@ -379,7 +378,6 @@ fn semantic_token_type_and_modifiers(
             SymbolKind::Impl => lsp_types::SemanticTokenType::TYPE,
             SymbolKind::Field => lsp_types::SemanticTokenType::PROPERTY,
             SymbolKind::TypeParam => lsp_types::SemanticTokenType::TYPE_PARAMETER,
-            SymbolKind::ConstParam => semantic_tokens::CONST_PARAMETER,
             SymbolKind::LifetimeParam => semantic_tokens::LIFETIME,
             SymbolKind::Label => semantic_tokens::LABEL,
             SymbolKind::ValueParam => lsp_types::SemanticTokenType::PARAMETER,
diff --git a/docs/user/manual.adoc b/docs/user/manual.adoc
index 75445a02e5..d4121b4011 100644
--- a/docs/user/manual.adoc
+++ b/docs/user/manual.adoc
@@ -339,7 +339,7 @@ interface Crate {
     /// Path to the root module of the crate.
     root_module: string;
     /// Edition of the crate.
-    edition: "2015" | "2018" | "2021";
+    edition: "2015" | "2018";
     /// Dependencies
     deps: Dep[];
     /// Should this crate be treated as a member of current "workspace".
diff --git a/xtask/src/dist.rs b/xtask/src/dist.rs
index 6bc34106b6..d59b88131a 100644
--- a/xtask/src/dist.rs
+++ b/xtask/src/dist.rs
@@ -63,7 +63,8 @@ fn dist_server() -> Result<()> {
         env::set_var("CC", "clang");
     }
 
-    cmd!("cargo build --manifest-path ./crates/rust-analyzer/Cargo.toml --bin rust-analyzer --target {target} --release").run()?;
+    let toolchain = toolchain(&target);
+    cmd!("cargo +{toolchain} build --manifest-path ./crates/rust-analyzer/Cargo.toml --bin rust-analyzer --target {target} --release").run()?;
 
     let suffix = exe_suffix(&target);
     let src =
@@ -117,6 +118,13 @@ fn exe_suffix(target: &str) -> String {
     }
 }
 
+fn toolchain(target: &str) -> String {
+    match target {
+        "aarch64-apple-darwin" => "beta".to_string(),
+        _ => "stable".to_string(),
+    }
+}
+
 fn gzip(src_path: &Path, dest_path: &Path) -> Result<()> {
     let mut encoder = GzEncoder::new(File::create(dest_path)?, Compression::best());
     let mut input = io::BufReader::new(File::open(src_path)?);


Test patch:
diff --git a/crates/hir_ty/src/tests/macros.rs b/crates/hir_ty/src/tests/macros.rs
index a7656b8648..23b79abc45 100644
--- a/crates/hir_ty/src/tests/macros.rs
+++ b/crates/hir_ty/src/tests/macros.rs
@@ -370,6 +370,37 @@ expand!();
     );
 }
 
+#[test]
+fn infer_macro_with_dollar_crate_in_def_site() {
+    check_types(
+        r#"
+//- /main.rs crate:main deps:foo
+use foo::expand;
+
+macro_rules! list {
+    ($($tt:tt)*) => { $($tt)* }
+}
+
+fn test() {
+    let r = expand!();
+    r;
+  //^ u128
+}
+
+//- /lib.rs crate:foo
+#[macro_export]
+macro_rules! expand {
+    () => { list!($crate::m!()) };
+}
+
+#[macro_export]
+macro_rules! m {
+    () => { 0u128 };
+}
+"#,
+    );
+}
+
 #[test]
 fn infer_type_value_non_legacy_macro_use_as() {
     check_infer(
diff --git a/crates/hir_ty/src/tests/simple.rs b/crates/hir_ty/src/tests/simple.rs
index 8d431b9201..a61282d5a7 100644
--- a/crates/hir_ty/src/tests/simple.rs
+++ b/crates/hir_ty/src/tests/simple.rs
@@ -2375,19 +2375,3 @@ fn infer_operator_overload() {
         "#]],
     );
 }
-
-#[test]
-fn infer_const_params() {
-    check_infer(
-        r#"
-        fn foo<const FOO: usize>() {
-            let bar = FOO;
-        }
-        "#,
-        expect![[r#"
-            27..49 '{     ...FOO; }': ()
-            37..40 'bar': usize
-            43..46 'FOO': usize
-        "#]],
-    );
-}
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlighting.html b/crates/ide/src/syntax_highlighting/test_data/highlighting.html
index 02270b0770..72ff9dd40e 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlighting.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlighting.html
@@ -118,10 +118,6 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
     <span class="keyword control">loop</span> <span class="punctuation">{</span><span class="punctuation">}</span>
 <span class="punctuation">}</span>
 
-<span class="keyword">fn</span> <span class="function declaration">const_param</span><span class="punctuation">&lt;</span><span class="keyword">const</span> <span class="const_param declaration">FOO</span><span class="punctuation">:</span> <span class="builtin_type">usize</span><span class="punctuation">&gt;</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">usize</span> <span class="punctuation">{</span>
-    <span class="const_param">FOO</span>
-<span class="punctuation">}</span>
-
 <span class="keyword">use</span> <span class="module">ops</span><span class="operator">::</span><span class="trait">Fn</span><span class="punctuation">;</span>
 <span class="keyword">fn</span> <span class="function declaration">baz</span><span class="punctuation">&lt;</span><span class="type_param declaration">F</span><span class="punctuation">:</span> <span class="trait">Fn</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="operator">-&gt;</span> <span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">&gt;</span><span class="punctuation">(</span><span class="value_param declaration callable">f</span><span class="punctuation">:</span> <span class="type_param">F</span><span class="punctuation">)</span> <span class="punctuation">{</span>
     <span class="value_param callable">f</span><span class="punctuation">(</span><span class="punctuation">)</span>
diff --git a/crates/ide/src/syntax_highlighting/tests.rs b/crates/ide/src/syntax_highlighting/tests.rs
index 30b5b648e9..e0df0d2b52 100644
--- a/crates/ide/src/syntax_highlighting/tests.rs
+++ b/crates/ide/src/syntax_highlighting/tests.rs
@@ -91,10 +91,6 @@ fn never() -> ! {
     loop {}
 }
 
-fn const_param<const FOO: usize>() -> usize {
-    FOO
-}
-
 use ops::Fn;
 fn baz<F: Fn() -> ()>(f: F) {
     f()