Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-def/src/lower.rs')
-rw-r--r--crates/hir-def/src/lower.rs100
1 files changed, 41 insertions, 59 deletions
diff --git a/crates/hir-def/src/lower.rs b/crates/hir-def/src/lower.rs
index df5847929c..6d1a3d1744 100644
--- a/crates/hir-def/src/lower.rs
+++ b/crates/hir-def/src/lower.rs
@@ -1,10 +1,7 @@
//! Context for lowering paths.
-use std::cell::{OnceCell, RefCell};
+use std::{cell::OnceCell, mem};
-use hir_expand::{
- span_map::{SpanMap, SpanMapRef},
- AstId, HirFileId, InFile,
-};
+use hir_expand::{span_map::SpanMap, AstId, HirFileId, InFile};
use span::{AstIdMap, AstIdNode};
use stdx::thin_vec::ThinVec;
use syntax::ast;
@@ -21,28 +18,11 @@ pub struct LowerCtx<'a> {
file_id: HirFileId,
span_map: OnceCell<SpanMap>,
ast_id_map: OnceCell<Arc<AstIdMap>>,
- impl_trait_bounds: RefCell<Vec<ThinVec<TypeBound>>>,
+ impl_trait_bounds: Vec<ThinVec<TypeBound>>,
// Prevent nested impl traits like `impl Foo<impl Bar>`.
- outer_impl_trait: RefCell<bool>,
- types_map: RefCell<(&'a mut TypesMap, &'a mut TypesSourceMap)>,
-}
-
-pub(crate) struct OuterImplTraitGuard<'a, 'b> {
- ctx: &'a LowerCtx<'b>,
- old: bool,
-}
-
-impl<'a, 'b> OuterImplTraitGuard<'a, 'b> {
- fn new(ctx: &'a LowerCtx<'b>, impl_trait: bool) -> Self {
- let old = ctx.outer_impl_trait.replace(impl_trait);
- Self { ctx, old }
- }
-}
-
-impl Drop for OuterImplTraitGuard<'_, '_> {
- fn drop(&mut self) {
- self.ctx.outer_impl_trait.replace(self.old);
- }
+ outer_impl_trait: bool,
+ types_map: &'a mut TypesMap,
+ types_source_map: &'a mut TypesSourceMap,
}
impl<'a> LowerCtx<'a> {
@@ -57,9 +37,10 @@ impl<'a> LowerCtx<'a> {
file_id,
span_map: OnceCell::new(),
ast_id_map: OnceCell::new(),
- impl_trait_bounds: RefCell::new(Vec::new()),
- outer_impl_trait: RefCell::default(),
- types_map: RefCell::new((types_map, types_source_map)),
+ impl_trait_bounds: Vec::new(),
+ outer_impl_trait: false,
+ types_map,
+ types_source_map,
}
}
@@ -75,17 +56,18 @@ impl<'a> LowerCtx<'a> {
file_id,
span_map,
ast_id_map: OnceCell::new(),
- impl_trait_bounds: RefCell::new(Vec::new()),
- outer_impl_trait: RefCell::default(),
- types_map: RefCell::new((types_map, types_source_map)),
+ impl_trait_bounds: Vec::new(),
+ outer_impl_trait: false,
+ types_map,
+ types_source_map,
}
}
- pub(crate) fn span_map(&self) -> SpanMapRef<'_> {
- self.span_map.get_or_init(|| self.db.span_map(self.file_id)).as_ref()
+ pub(crate) fn span_map(&self) -> &SpanMap {
+ self.span_map.get_or_init(|| self.db.span_map(self.file_id))
}
- pub(crate) fn lower_path(&self, ast: ast::Path) -> Option<Path> {
+ pub(crate) fn lower_path(&mut self, ast: ast::Path) -> Option<Path> {
Path::from_src(self, ast)
}
@@ -96,44 +78,44 @@ impl<'a> LowerCtx<'a> {
)
}
- pub fn update_impl_traits_bounds(&self, bounds: ThinVec<TypeBound>) {
- self.impl_trait_bounds.borrow_mut().push(bounds);
+ pub fn update_impl_traits_bounds_from_type_ref(&mut self, type_ref: TypeRefId) {
+ TypeRef::walk(type_ref, self.types_map, &mut |tr| {
+ if let TypeRef::ImplTrait(bounds) = tr {
+ self.impl_trait_bounds.push(bounds.clone());
+ }
+ });
}
- pub fn take_impl_traits_bounds(&self) -> Vec<ThinVec<TypeBound>> {
- self.impl_trait_bounds.take()
+ pub fn take_impl_traits_bounds(&mut self) -> Vec<ThinVec<TypeBound>> {
+ mem::take(&mut self.impl_trait_bounds)
}
pub(crate) fn outer_impl_trait(&self) -> bool {
- *self.outer_impl_trait.borrow()
+ self.outer_impl_trait
}
- pub(crate) fn outer_impl_trait_scope<'b>(
- &'b self,
+ pub(crate) fn with_outer_impl_trait_scope<R>(
+ &mut self,
impl_trait: bool,
- ) -> OuterImplTraitGuard<'b, 'a> {
- OuterImplTraitGuard::new(self, impl_trait)
+ f: impl FnOnce(&mut Self) -> R,
+ ) -> R {
+ let old = mem::replace(&mut self.outer_impl_trait, impl_trait);
+ let result = f(self);
+ self.outer_impl_trait = old;
+ result
}
- pub(crate) fn alloc_type_ref(&self, type_ref: TypeRef, node: TypePtr) -> TypeRefId {
- let mut types_map = self.types_map.borrow_mut();
- let (types_map, types_source_map) = &mut *types_map;
- let id = types_map.types.alloc(type_ref);
- types_source_map.types_map_back.insert(id, InFile::new(self.file_id, node));
+ pub(crate) fn alloc_type_ref(&mut self, type_ref: TypeRef, node: TypePtr) -> TypeRefId {
+ let id = self.types_map.types.alloc(type_ref);
+ self.types_source_map.types_map_back.insert(id, InFile::new(self.file_id, node));
id
}
- pub(crate) fn alloc_type_ref_desugared(&self, type_ref: TypeRef) -> TypeRefId {
- self.types_map.borrow_mut().0.types.alloc(type_ref)
- }
-
- pub(crate) fn alloc_error_type(&self) -> TypeRefId {
- self.types_map.borrow_mut().0.types.alloc(TypeRef::Error)
+ pub(crate) fn alloc_type_ref_desugared(&mut self, type_ref: TypeRef) -> TypeRefId {
+ self.types_map.types.alloc(type_ref)
}
- // FIXME: If we alloc while holding this, well... Bad Things will happen. Need to change this
- // to use proper mutability instead of interior mutability.
- pub(crate) fn types_map(&self) -> std::cell::Ref<'_, TypesMap> {
- std::cell::Ref::map(self.types_map.borrow(), |it| &*it.0)
+ pub(crate) fn alloc_error_type(&mut self) -> TypeRefId {
+ self.types_map.types.alloc(TypeRef::Error)
}
}