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.rs | 100 |
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) } } |