From 41658de22724df44ea2c66b06eaf6bf890aa211a Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Mon, 28 Oct 2024 17:38:37 +0200 Subject: [PATCH] Cleanup TypeRef lowering By removing interior mutability from it. --- crates/hir-def/src/body/lower.rs | 16 +++-- crates/hir-def/src/expander.rs | 4 +- crates/hir-def/src/generics.rs | 19 +++-- crates/hir-def/src/hir/type_ref.rs | 17 ++--- crates/hir-def/src/item_tree/lower.rs | 78 ++++++++++---------- crates/hir-def/src/lower.rs | 100 +++++++++++--------------- crates/hir-def/src/path.rs | 4 +- crates/hir-def/src/path/lower.rs | 54 ++++++-------- crates/hir-ty/src/display.rs | 4 +- crates/hir-ty/src/lower.rs | 4 +- crates/hir/src/semantics.rs | 12 ++-- crates/hir/src/source_analyzer.rs | 9 +-- 12 files changed, 151 insertions(+), 170 deletions(-) diff --git a/crates/hir-def/src/body/lower.rs b/crates/hir-def/src/body/lower.rs index 0b108b54e6..1ab49e9156 100644 --- a/crates/hir-def/src/body/lower.rs +++ b/crates/hir-def/src/body/lower.rs @@ -407,7 +407,7 @@ impl ExprCollector<'_> { let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing); let generic_args = e .generic_arg_list() - .and_then(|it| GenericArgs::from_ast(&self.ctx(), it)) + .and_then(|it| GenericArgs::from_ast(&mut self.ctx(), it)) .map(Box::new); self.alloc_expr( Expr::MethodCall { receiver, method_name, args, generic_args }, @@ -533,7 +533,7 @@ impl ExprCollector<'_> { ast::Expr::TryExpr(e) => self.collect_try_operator(syntax_ptr, e), ast::Expr::CastExpr(e) => { let expr = self.collect_expr_opt(e.expr()); - let type_ref = TypeRef::from_ast_opt(&self.ctx(), e.ty()); + let type_ref = TypeRef::from_ast_opt(&mut self.ctx(), e.ty()); self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr) } ast::Expr::RefExpr(e) => { @@ -572,13 +572,15 @@ impl ExprCollector<'_> { arg_types.reserve_exact(num_params); for param in pl.params() { let pat = this.collect_pat_top(param.pat()); - let type_ref = param.ty().map(|it| TypeRef::from_ast(&this.ctx(), it)); + let type_ref = param.ty().map(|it| TypeRef::from_ast(&mut this.ctx(), it)); args.push(pat); arg_types.push(type_ref); } } - let ret_type = - e.ret_type().and_then(|r| r.ty()).map(|it| TypeRef::from_ast(&this.ctx(), it)); + let ret_type = e + .ret_type() + .and_then(|r| r.ty()) + .map(|it| TypeRef::from_ast(&mut this.ctx(), it)); let prev_is_lowering_coroutine = mem::take(&mut this.is_lowering_coroutine); let prev_try_block_label = this.current_try_block_label.take(); @@ -705,7 +707,7 @@ impl ExprCollector<'_> { ast::Expr::UnderscoreExpr(_) => self.alloc_expr(Expr::Underscore, syntax_ptr), ast::Expr::AsmExpr(e) => self.lower_inline_asm(e, syntax_ptr), ast::Expr::OffsetOfExpr(e) => { - let container = TypeRef::from_ast_opt(&self.ctx(), e.ty()); + let container = TypeRef::from_ast_opt(&mut self.ctx(), e.ty()); let fields = e.fields().map(|it| it.as_name()).collect(); self.alloc_expr(Expr::OffsetOf(OffsetOf { container, fields }), syntax_ptr) } @@ -1317,7 +1319,7 @@ impl ExprCollector<'_> { return; } let pat = self.collect_pat_top(stmt.pat()); - let type_ref = stmt.ty().map(|it| TypeRef::from_ast(&self.ctx(), it)); + let type_ref = stmt.ty().map(|it| TypeRef::from_ast(&mut self.ctx(), it)); let initializer = stmt.initializer().map(|e| self.collect_expr(e)); let else_branch = stmt .let_else() diff --git a/crates/hir-def/src/expander.rs b/crates/hir-def/src/expander.rs index d430733fca..5315c1c6fb 100644 --- a/crates/hir-def/src/expander.rs +++ b/crates/hir-def/src/expander.rs @@ -161,14 +161,14 @@ impl Expander { types_map: &mut TypesMap, types_source_map: &mut TypesSourceMap, ) -> Option { - let ctx = LowerCtx::with_span_map_cell( + let mut ctx = LowerCtx::with_span_map_cell( db, self.current_file_id, self.span_map.clone(), types_map, types_source_map, ); - Path::from_src(&ctx, path) + Path::from_src(&mut ctx, path) } fn within_limit( diff --git a/crates/hir-def/src/generics.rs b/crates/hir-def/src/generics.rs index 6b79850e9c..11e9bb0d88 100644 --- a/crates/hir-def/src/generics.rs +++ b/crates/hir-def/src/generics.rs @@ -451,7 +451,7 @@ pub(crate) struct GenericParamsCollector { impl GenericParamsCollector { pub(crate) fn fill( &mut self, - lower_ctx: &LowerCtx<'_>, + lower_ctx: &mut LowerCtx<'_>, node: &dyn HasGenericParams, add_param_attrs: impl FnMut( Either, @@ -468,7 +468,7 @@ impl GenericParamsCollector { pub(crate) fn fill_bounds( &mut self, - lower_ctx: &LowerCtx<'_>, + lower_ctx: &mut LowerCtx<'_>, type_bounds: Option, target: Either, ) { @@ -479,7 +479,7 @@ impl GenericParamsCollector { fn fill_params( &mut self, - lower_ctx: &LowerCtx<'_>, + lower_ctx: &mut LowerCtx<'_>, params: ast::GenericParamList, mut add_param_attrs: impl FnMut( Either, @@ -535,7 +535,11 @@ impl GenericParamsCollector { } } - fn fill_where_predicates(&mut self, lower_ctx: &LowerCtx<'_>, where_clause: ast::WhereClause) { + fn fill_where_predicates( + &mut self, + lower_ctx: &mut LowerCtx<'_>, + where_clause: ast::WhereClause, + ) { for pred in where_clause.predicates() { let target = if let Some(type_ref) = pred.ty() { Either::Left(TypeRef::from_ast(lower_ctx, type_ref)) @@ -569,7 +573,7 @@ impl GenericParamsCollector { fn add_where_predicate_from_bound( &mut self, - lower_ctx: &LowerCtx<'_>, + lower_ctx: &mut LowerCtx<'_>, bound: ast::TypeBound, hrtb_lifetimes: Option<&[Name]>, target: Either, @@ -670,8 +674,9 @@ impl GenericParamsCollector { { let (mut macro_types_map, mut macro_types_source_map) = (TypesMap::default(), TypesSourceMap::default()); - let ctx = expander.ctx(db, &mut macro_types_map, &mut macro_types_source_map); - let type_ref = TypeRef::from_ast(&ctx, expanded.tree()); + let mut ctx = + expander.ctx(db, &mut macro_types_map, &mut macro_types_source_map); + let type_ref = TypeRef::from_ast(&mut ctx, expanded.tree()); self.fill_implicit_impl_trait_args( db, generics_types_map, diff --git a/crates/hir-def/src/hir/type_ref.rs b/crates/hir-def/src/hir/type_ref.rs index 2582340c0f..4d83ef99c8 100644 --- a/crates/hir-def/src/hir/type_ref.rs +++ b/crates/hir-def/src/hir/type_ref.rs @@ -98,7 +98,7 @@ pub struct TraitRef { impl TraitRef { /// Converts an `ast::PathType` to a `hir::TraitRef`. - pub(crate) fn from_ast(ctx: &LowerCtx<'_>, node: ast::Type) -> Option { + pub(crate) fn from_ast(ctx: &mut LowerCtx<'_>, node: ast::Type) -> Option { // FIXME: Use `Path::from_src` match node { ast::Type::PathType(path) => { @@ -240,7 +240,7 @@ pub enum TraitBoundModifier { impl TypeRef { /// Converts an `ast::TypeRef` to a `hir::TypeRef`. - pub fn from_ast(ctx: &LowerCtx<'_>, node: ast::Type) -> TypeRefId { + pub fn from_ast(ctx: &mut LowerCtx<'_>, node: ast::Type) -> TypeRefId { let ty = match &node { ast::Type::ParenType(inner) => return TypeRef::from_ast_opt(ctx, inner.ty()), ast::Type::TupleType(inner) => TypeRef::Tuple(EmptyOptimizedThinVec::from_iter( @@ -321,8 +321,9 @@ impl TypeRef { // Disallow nested impl traits TypeRef::Error } else { - let _guard = ctx.outer_impl_trait_scope(true); - TypeRef::ImplTrait(type_bounds_from_ast(ctx, inner.type_bound_list())) + ctx.with_outer_impl_trait_scope(true, |ctx| { + TypeRef::ImplTrait(type_bounds_from_ast(ctx, inner.type_bound_list())) + }) } } ast::Type::DynTraitType(inner) => { @@ -336,7 +337,7 @@ impl TypeRef { ctx.alloc_type_ref(ty, AstPtr::new(&node)) } - pub(crate) fn from_ast_opt(ctx: &LowerCtx<'_>, node: Option) -> TypeRefId { + pub(crate) fn from_ast_opt(ctx: &mut LowerCtx<'_>, node: Option) -> TypeRefId { match node { Some(node) => TypeRef::from_ast(ctx, node), None => ctx.alloc_error_type(), @@ -410,7 +411,7 @@ impl TypeRef { } pub(crate) fn type_bounds_from_ast( - lower_ctx: &LowerCtx<'_>, + lower_ctx: &mut LowerCtx<'_>, type_bounds_opt: Option, ) -> ThinVec { if let Some(type_bounds) = type_bounds_opt { @@ -423,8 +424,8 @@ pub(crate) fn type_bounds_from_ast( } impl TypeBound { - pub(crate) fn from_ast(ctx: &LowerCtx<'_>, node: ast::TypeBound) -> Self { - let lower_path_type = |path_type: ast::PathType| ctx.lower_path(path_type.path()?); + pub(crate) fn from_ast(ctx: &mut LowerCtx<'_>, node: ast::TypeBound) -> Self { + let mut lower_path_type = |path_type: ast::PathType| ctx.lower_path(path_type.path()?); match node.kind() { ast::TypeBoundKind::PathType(path_type) => { diff --git a/crates/hir-def/src/item_tree/lower.rs b/crates/hir-def/src/item_tree/lower.rs index bd17fce37b..d519c1708b 100644 --- a/crates/hir-def/src/item_tree/lower.rs +++ b/crates/hir-def/src/item_tree/lower.rs @@ -234,11 +234,11 @@ impl<'a> Ctx<'a> { fn lower_struct(&mut self, strukt: &ast::Struct) -> Option> { let (mut types_map, mut types_source_map) = (TypesMap::default(), TypesSourceMap::default()); - let body_ctx = self.body_ctx(&mut types_map, &mut types_source_map); + let mut body_ctx = self.body_ctx(&mut types_map, &mut types_source_map); let visibility = self.lower_visibility(strukt); let name = strukt.name()?.as_name(); let ast_id = self.source_ast_id_map.ast_id(strukt); - let (fields, kind, attrs) = self.lower_fields(&strukt.kind(), &body_ctx); + let (fields, kind, attrs) = self.lower_fields(&strukt.kind(), &mut body_ctx); let (generic_params, generics_source_map) = self.lower_generic_params(HasImplicitSelf::No, strukt); types_map.shrink_to_fit(); @@ -273,7 +273,7 @@ impl<'a> Ctx<'a> { fn lower_fields( &mut self, strukt_kind: &ast::StructKind, - body_ctx: &LowerCtx<'_>, + body_ctx: &mut LowerCtx<'_>, ) -> (Box<[Field]>, FieldsShape, Vec<(usize, RawAttrs)>) { match strukt_kind { ast::StructKind::Record(it) => { @@ -308,7 +308,11 @@ impl<'a> Ctx<'a> { } } - fn lower_record_field(&mut self, field: &ast::RecordField, body_ctx: &LowerCtx<'_>) -> Field { + fn lower_record_field( + &mut self, + field: &ast::RecordField, + body_ctx: &mut LowerCtx<'_>, + ) -> Field { let name = match field.name() { Some(name) => name.as_name(), None => Name::missing(), @@ -323,7 +327,7 @@ impl<'a> Ctx<'a> { &mut self, idx: usize, field: &ast::TupleField, - body_ctx: &LowerCtx<'_>, + body_ctx: &mut LowerCtx<'_>, ) -> Field { let name = Name::new_tuple_field(idx); let visibility = self.lower_visibility(field); @@ -334,13 +338,13 @@ impl<'a> Ctx<'a> { fn lower_union(&mut self, union: &ast::Union) -> Option> { let (mut types_map, mut types_source_map) = (TypesMap::default(), TypesSourceMap::default()); - let body_ctx = self.body_ctx(&mut types_map, &mut types_source_map); + let mut body_ctx = self.body_ctx(&mut types_map, &mut types_source_map); let visibility = self.lower_visibility(union); let name = union.name()?.as_name(); let ast_id = self.source_ast_id_map.ast_id(union); let (fields, _, attrs) = match union.record_field_list() { Some(record_field_list) => { - self.lower_fields(&StructKind::Record(record_field_list), &body_ctx) + self.lower_fields(&StructKind::Record(record_field_list), &mut body_ctx) } None => (Box::default(), FieldsShape::Record, Vec::default()), }; @@ -409,12 +413,12 @@ impl<'a> Ctx<'a> { fn lower_variant(&mut self, variant: &ast::Variant) -> Idx { let (mut types_map, mut types_source_map) = (TypesMap::default(), TypesSourceMap::default()); - let body_ctx = self.body_ctx(&mut types_map, &mut types_source_map); + let mut body_ctx = self.body_ctx(&mut types_map, &mut types_source_map); let name = match variant.name() { Some(name) => name.as_name(), None => Name::missing(), }; - let (fields, kind, attrs) = self.lower_fields(&variant.kind(), &body_ctx); + let (fields, kind, attrs) = self.lower_fields(&variant.kind(), &mut body_ctx); let ast_id = self.source_ast_id_map.ast_id(variant); types_map.shrink_to_fit(); types_source_map.shrink_to_fit(); @@ -436,7 +440,7 @@ impl<'a> Ctx<'a> { fn lower_function(&mut self, func: &ast::Fn) -> Option> { let (mut types_map, mut types_source_map) = (TypesMap::default(), TypesSourceMap::default()); - let body_ctx = self.body_ctx(&mut types_map, &mut types_source_map); + let mut body_ctx = self.body_ctx(&mut types_map, &mut types_source_map); let visibility = self.lower_visibility(func); let name = func.name()?.as_name(); @@ -457,7 +461,7 @@ impl<'a> Ctx<'a> { RawAttrs::new(self.db.upcast(), &self_param, self.span_map()), ); let self_type = match self_param.ty() { - Some(type_ref) => TypeRef::from_ast(&body_ctx, type_ref), + Some(type_ref) => TypeRef::from_ast(&mut body_ctx, type_ref), None => { let self_type = body_ctx.alloc_type_ref_desugared(TypeRef::Path( Name::new_symbol_root(sym::Self_.clone()).into(), @@ -492,7 +496,7 @@ impl<'a> Ctx<'a> { Param { type_ref: None } } None => { - let type_ref = TypeRef::from_ast_opt(&body_ctx, param.ty()); + let type_ref = TypeRef::from_ast_opt(&mut body_ctx, param.ty()); Param { type_ref: Some(type_ref) } } }; @@ -502,7 +506,7 @@ impl<'a> Ctx<'a> { let ret_type = match func.ret_type() { Some(rt) => match rt.ty() { - Some(type_ref) => TypeRef::from_ast(&body_ctx, type_ref), + Some(type_ref) => TypeRef::from_ast(&mut body_ctx, type_ref), None if rt.thin_arrow_token().is_some() => body_ctx.alloc_error_type(), None => body_ctx.alloc_type_ref_desugared(TypeRef::unit()), }, @@ -581,11 +585,11 @@ impl<'a> Ctx<'a> { ) -> Option> { let (mut types_map, mut types_source_map) = (TypesMap::default(), TypesSourceMap::default()); - let body_ctx = self.body_ctx(&mut types_map, &mut types_source_map); + let mut body_ctx = self.body_ctx(&mut types_map, &mut types_source_map); let name = type_alias.name()?.as_name(); - let type_ref = type_alias.ty().map(|it| TypeRef::from_ast(&body_ctx, it)); + let type_ref = type_alias.ty().map(|it| TypeRef::from_ast(&mut body_ctx, it)); let visibility = self.lower_visibility(type_alias); - let bounds = self.lower_type_bounds(type_alias, &body_ctx); + let bounds = self.lower_type_bounds(type_alias, &mut body_ctx); let ast_id = self.source_ast_id_map.ast_id(type_alias); let (generic_params, generics_source_map) = self.lower_generic_params(HasImplicitSelf::No, type_alias); @@ -612,9 +616,9 @@ impl<'a> Ctx<'a> { fn lower_static(&mut self, static_: &ast::Static) -> Option> { let (mut types_map, mut types_source_map) = (TypesMap::default(), TypesSourceMap::default()); - let body_ctx = self.body_ctx(&mut types_map, &mut types_source_map); + let mut body_ctx = self.body_ctx(&mut types_map, &mut types_source_map); let name = static_.name()?.as_name(); - let type_ref = TypeRef::from_ast_opt(&body_ctx, static_.ty()); + let type_ref = TypeRef::from_ast_opt(&mut body_ctx, static_.ty()); let visibility = self.lower_visibility(static_); let mutable = static_.mut_token().is_some(); let has_safe_kw = static_.safe_token().is_some(); @@ -639,9 +643,9 @@ impl<'a> Ctx<'a> { fn lower_const(&mut self, konst: &ast::Const) -> FileItemTreeId { let (mut types_map, mut types_source_map) = (TypesMap::default(), TypesSourceMap::default()); - let body_ctx = self.body_ctx(&mut types_map, &mut types_source_map); + let mut body_ctx = self.body_ctx(&mut types_map, &mut types_source_map); let name = konst.name().map(|it| it.as_name()); - let type_ref = TypeRef::from_ast_opt(&body_ctx, konst.ty()); + let type_ref = TypeRef::from_ast_opt(&mut body_ctx, konst.ty()); let visibility = self.lower_visibility(konst); let ast_id = self.source_ast_id_map.ast_id(konst); types_map.shrink_to_fit(); @@ -724,14 +728,14 @@ impl<'a> Ctx<'a> { fn lower_impl(&mut self, impl_def: &ast::Impl) -> FileItemTreeId { let (mut types_map, mut types_source_map) = (TypesMap::default(), TypesSourceMap::default()); - let body_ctx = self.body_ctx(&mut types_map, &mut types_source_map); + let mut body_ctx = self.body_ctx(&mut types_map, &mut types_source_map); let ast_id = self.source_ast_id_map.ast_id(impl_def); // FIXME: If trait lowering fails, due to a non PathType for example, we treat this impl // as if it was an non-trait impl. Ideally we want to create a unique missing ref that only // equals itself. - let self_ty = TypeRef::from_ast_opt(&body_ctx, impl_def.self_ty()); - let target_trait = impl_def.trait_().and_then(|tr| TraitRef::from_ast(&body_ctx, tr)); + let self_ty = TypeRef::from_ast_opt(&mut body_ctx, impl_def.self_ty()); + let target_trait = impl_def.trait_().and_then(|tr| TraitRef::from_ast(&mut body_ctx, tr)); let is_negative = impl_def.excl_token().is_some(); let is_unsafe = impl_def.unsafe_token().is_some(); @@ -870,13 +874,8 @@ impl<'a> Ctx<'a> { ) -> (Arc, TypesSourceMap) { let (mut types_map, mut types_source_map) = (TypesMap::default(), TypesSourceMap::default()); - let body_ctx = self.body_ctx(&mut types_map, &mut types_source_map); + let mut body_ctx = self.body_ctx(&mut types_map, &mut types_source_map); debug_assert!(self.generic_param_attr_buffer.is_empty(),); - let add_param_attrs = |item: Either, - param| { - let attrs = RawAttrs::new(self.db.upcast(), ¶m, body_ctx.span_map()); - debug_assert!(self.generic_param_attr_buffer.insert(item, attrs).is_none()); - }; body_ctx.take_impl_traits_bounds(); let mut generics = GenericParamsCollector::default(); @@ -892,16 +891,19 @@ impl<'a> Ctx<'a> { ); // add super traits as bounds on Self // i.e., `trait Foo: Bar` is equivalent to `trait Foo where Self: Bar` - generics.fill_bounds( - &body_ctx, - bounds, - Either::Left(body_ctx.alloc_type_ref_desugared(TypeRef::Path( - Name::new_symbol_root(sym::Self_.clone()).into(), - ))), - ); + let bound_target = Either::Left(body_ctx.alloc_type_ref_desugared(TypeRef::Path( + Name::new_symbol_root(sym::Self_.clone()).into(), + ))); + generics.fill_bounds(&mut body_ctx, bounds, bound_target); } - generics.fill(&body_ctx, node, add_param_attrs); + let span_map = body_ctx.span_map().clone(); + let add_param_attrs = |item: Either, + param| { + let attrs = RawAttrs::new(self.db.upcast(), ¶m, span_map.as_ref()); + debug_assert!(self.generic_param_attr_buffer.insert(item, attrs).is_none()); + }; + generics.fill(&mut body_ctx, node, add_param_attrs); let generics = generics.finish(types_map, &mut types_source_map); (generics, types_source_map) @@ -910,7 +912,7 @@ impl<'a> Ctx<'a> { fn lower_type_bounds( &mut self, node: &dyn ast::HasTypeBounds, - body_ctx: &LowerCtx<'_>, + body_ctx: &mut LowerCtx<'_>, ) -> Box<[TypeBound]> { match node.type_bound_list() { Some(bound_list) => { 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, ast_id_map: OnceCell>, - impl_trait_bounds: RefCell>>, + impl_trait_bounds: Vec>, // Prevent nested impl traits like `impl Foo`. - outer_impl_trait: RefCell, - 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 { + pub(crate) fn lower_path(&mut self, ast: ast::Path) -> Option { Path::from_src(self, ast) } @@ -96,44 +78,44 @@ impl<'a> LowerCtx<'a> { ) } - pub fn update_impl_traits_bounds(&self, bounds: ThinVec) { - 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> { - self.impl_trait_bounds.take() + pub fn take_impl_traits_bounds(&mut self) -> Vec> { + 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( + &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_type_ref_desugared(&mut self, type_ref: TypeRef) -> TypeRefId { + self.types_map.types.alloc(type_ref) } - pub(crate) fn alloc_error_type(&self) -> TypeRefId { - self.types_map.borrow_mut().0.types.alloc(TypeRef::Error) - } - - // 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) } } diff --git a/crates/hir-def/src/path.rs b/crates/hir-def/src/path.rs index dc6947c5b5..aa2c4a6f1b 100644 --- a/crates/hir-def/src/path.rs +++ b/crates/hir-def/src/path.rs @@ -121,7 +121,7 @@ pub enum GenericArg { impl Path { /// Converts an `ast::Path` to `Path`. Works with use trees. /// It correctly handles `$crate` based path from macro call. - pub fn from_src(ctx: &LowerCtx<'_>, path: ast::Path) -> Option { + pub fn from_src(ctx: &mut LowerCtx<'_>, path: ast::Path) -> Option { lower::lower_path(ctx, path) } @@ -284,7 +284,7 @@ impl<'a> PathSegments<'a> { impl GenericArgs { pub(crate) fn from_ast( - lower_ctx: &LowerCtx<'_>, + lower_ctx: &mut LowerCtx<'_>, node: ast::GenericArgList, ) -> Option { lower::lower_generic_args(lower_ctx, node) diff --git a/crates/hir-def/src/path/lower.rs b/crates/hir-def/src/path/lower.rs index c328b9c6ce..553e615b94 100644 --- a/crates/hir-def/src/path/lower.rs +++ b/crates/hir-def/src/path/lower.rs @@ -19,12 +19,11 @@ use crate::{ /// Converts an `ast::Path` to `Path`. Works with use trees. /// It correctly handles `$crate` based path from macro call. -pub(super) fn lower_path(ctx: &LowerCtx<'_>, mut path: ast::Path) -> Option { +pub(super) fn lower_path(ctx: &mut LowerCtx<'_>, mut path: ast::Path) -> Option { let mut kind = PathKind::Plain; let mut type_anchor = None; let mut segments = Vec::new(); let mut generic_args = Vec::new(); - let span_map = ctx.span_map(); loop { let segment = path.segment()?; @@ -37,7 +36,7 @@ pub(super) fn lower_path(ctx: &LowerCtx<'_>, mut path: ast::Path) -> Option, mut path: ast::Path) -> Option, mut path: ast::Path) -> Option, + lower_ctx: &mut LowerCtx<'_>, node: ast::GenericArgList, ) -> Option { let mut args = Vec::new(); @@ -192,13 +191,7 @@ pub(super) fn lower_generic_args( match generic_arg { ast::GenericArg::TypeArg(type_arg) => { let type_ref = TypeRef::from_ast_opt(lower_ctx, type_arg.ty()); - let types_map = lower_ctx.types_map(); - TypeRef::walk(type_ref, &types_map, &mut |tr| { - if let TypeRef::ImplTrait(bounds) = tr { - lower_ctx.update_impl_traits_bounds(bounds.clone()); - } - }); - drop(types_map); + lower_ctx.update_impl_traits_bounds_from_type_ref(type_ref); args.push(GenericArg::Type(type_ref)); } ast::GenericArg::AssocTypeArg(assoc_type_arg) => { @@ -208,27 +201,22 @@ pub(super) fn lower_generic_args( } if let Some(name_ref) = assoc_type_arg.name_ref() { // Nested impl traits like `impl Foo` are allowed - let _guard = lower_ctx.outer_impl_trait_scope(false); - let name = name_ref.as_name(); - let args = assoc_type_arg - .generic_arg_list() - .and_then(|args| lower_generic_args(lower_ctx, args)); - let type_ref = assoc_type_arg.ty().map(|it| TypeRef::from_ast(lower_ctx, it)); - let type_ref = type_ref.inspect(|&tr| { - let types_map = lower_ctx.types_map(); - TypeRef::walk(tr, &types_map, &mut |tr| { - if let TypeRef::ImplTrait(bounds) = tr { - lower_ctx.update_impl_traits_bounds(bounds.clone()); - } - }); - drop(types_map); + lower_ctx.with_outer_impl_trait_scope(false, |lower_ctx| { + let name = name_ref.as_name(); + let args = assoc_type_arg + .generic_arg_list() + .and_then(|args| lower_generic_args(lower_ctx, args)); + let type_ref = + assoc_type_arg.ty().map(|it| TypeRef::from_ast(lower_ctx, it)); + let type_ref = type_ref + .inspect(|&tr| lower_ctx.update_impl_traits_bounds_from_type_ref(tr)); + let bounds = if let Some(l) = assoc_type_arg.type_bound_list() { + l.bounds().map(|it| TypeBound::from_ast(lower_ctx, it)).collect() + } else { + Box::default() + }; + bindings.push(AssociatedTypeBinding { name, args, type_ref, bounds }); }); - let bounds = if let Some(l) = assoc_type_arg.type_bound_list() { - l.bounds().map(|it| TypeBound::from_ast(lower_ctx, it)).collect() - } else { - Box::default() - }; - bindings.push(AssociatedTypeBinding { name, args, type_ref, bounds }); } } ast::GenericArg::LifetimeArg(lifetime_arg) => { @@ -258,7 +246,7 @@ pub(super) fn lower_generic_args( /// Collect `GenericArgs` from the parts of a fn-like path, i.e. `Fn(X, Y) /// -> Z` (which desugars to `Fn<(X, Y), Output=Z>`). fn lower_generic_args_from_fn_path( - ctx: &LowerCtx<'_>, + ctx: &mut LowerCtx<'_>, params: Option, ret_type: Option, ) -> Option { diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs index 277dabe9aa..4e95bdf219 100644 --- a/crates/hir-ty/src/display.rs +++ b/crates/hir-ty/src/display.rs @@ -2033,7 +2033,7 @@ impl HirDisplayWithTypesMap for TypeRefId { TypeRef::Macro(macro_call) => { let (mut types_map, mut types_source_map) = (TypesMap::default(), TypesSourceMap::default()); - let ctx = hir_def::lower::LowerCtx::new( + let mut ctx = hir_def::lower::LowerCtx::new( f.db.upcast(), macro_call.file_id, &mut types_map, @@ -2041,7 +2041,7 @@ impl HirDisplayWithTypesMap for TypeRefId { ); let macro_call = macro_call.to_node(f.db.upcast()); match macro_call.path() { - Some(path) => match Path::from_src(&ctx, path) { + Some(path) => match Path::from_src(&mut ctx, path) { Some(path) => path.hir_fmt(f, &types_map)?, None => write!(f, "{{macro}}")?, }, diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index e3a92e52f6..ee9fd02cdf 100644 --- a/crates/hir-ty/src/lower.rs +++ b/crates/hir-ty/src/lower.rs @@ -465,13 +465,13 @@ impl<'a> TyLoweringContext<'a> { let (mut types_map, mut types_source_map) = (TypesMap::default(), TypesSourceMap::default()); - let ctx = expander.ctx( + let mut ctx = expander.ctx( self.db.upcast(), &mut types_map, &mut types_source_map, ); // FIXME: Report syntax errors in expansion here - let type_ref = TypeRef::from_ast(&ctx, expanded.tree()); + let type_ref = TypeRef::from_ast(&mut ctx, expanded.tree()); drop(expander); diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index feb9a344d8..29c2660554 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs @@ -1271,9 +1271,9 @@ impl<'db> SemanticsImpl<'db> { let analyze = self.analyze(ty.syntax())?; let (mut types_map, mut types_source_map) = (TypesMap::default(), TypesSourceMap::default()); - let ctx = + let mut ctx = LowerCtx::new(self.db.upcast(), analyze.file_id, &mut types_map, &mut types_source_map); - let type_ref = crate::TypeRef::from_ast(&ctx, ty.clone()); + let type_ref = crate::TypeRef::from_ast(&mut ctx, ty.clone()); let ty = hir_ty::TyLoweringContext::new_maybe_unowned( self.db, &analyze.resolver, @@ -1289,9 +1289,9 @@ impl<'db> SemanticsImpl<'db> { let analyze = self.analyze(path.syntax())?; let (mut types_map, mut types_source_map) = (TypesMap::default(), TypesSourceMap::default()); - let ctx = + let mut ctx = LowerCtx::new(self.db.upcast(), analyze.file_id, &mut types_map, &mut types_source_map); - let hir_path = Path::from_src(&ctx, path.clone())?; + let hir_path = Path::from_src(&mut ctx, path.clone())?; match analyze.resolver.resolve_path_in_type_ns_fully(self.db.upcast(), &hir_path)? { TypeNs::TraitId(id) => Some(Trait { id }), _ => None, @@ -1974,9 +1974,9 @@ impl SemanticsScope<'_> { pub fn speculative_resolve(&self, ast_path: &ast::Path) -> Option { let (mut types_map, mut types_source_map) = (TypesMap::default(), TypesSourceMap::default()); - let ctx = + let mut ctx = LowerCtx::new(self.db.upcast(), self.file_id, &mut types_map, &mut types_source_map); - let path = Path::from_src(&ctx, ast_path.clone())?; + let path = Path::from_src(&mut ctx, ast_path.clone())?; resolve_hir_path( self.db, &self.resolver, diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs index 8d6e228e14..c16454cff6 100644 --- a/crates/hir/src/source_analyzer.rs +++ b/crates/hir/src/source_analyzer.rs @@ -616,9 +616,9 @@ impl SourceAnalyzer { ) -> Option { let (mut types_map, mut types_source_map) = (TypesMap::default(), TypesSourceMap::default()); - let ctx = + let mut ctx = LowerCtx::new(db.upcast(), macro_call.file_id, &mut types_map, &mut types_source_map); - let path = macro_call.value.path().and_then(|ast| Path::from_src(&ctx, ast))?; + let path = macro_call.value.path().and_then(|ast| Path::from_src(&mut ctx, ast))?; self.resolver .resolve_path_as_macro(db.upcast(), path.mod_path()?, Some(MacroSubNs::Bang)) .map(|(it, _)| it.into()) @@ -731,8 +731,9 @@ impl SourceAnalyzer { let (mut types_map, mut types_source_map) = (TypesMap::default(), TypesSourceMap::default()); - let ctx = LowerCtx::new(db.upcast(), self.file_id, &mut types_map, &mut types_source_map); - let hir_path = Path::from_src(&ctx, path.clone())?; + let mut ctx = + LowerCtx::new(db.upcast(), self.file_id, &mut types_map, &mut types_source_map); + let hir_path = Path::from_src(&mut ctx, path.clone())?; // Case where path is a qualifier of a use tree, e.g. foo::bar::{Baz, Qux} where we are // trying to resolve foo::bar.