Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/hir-def/src/body/lower.rs16
-rw-r--r--crates/hir-def/src/expander.rs4
-rw-r--r--crates/hir-def/src/generics.rs19
-rw-r--r--crates/hir-def/src/hir/type_ref.rs17
-rw-r--r--crates/hir-def/src/item_tree/lower.rs78
-rw-r--r--crates/hir-def/src/lower.rs100
-rw-r--r--crates/hir-def/src/path.rs4
-rw-r--r--crates/hir-def/src/path/lower.rs54
-rw-r--r--crates/hir-ty/src/display.rs4
-rw-r--r--crates/hir-ty/src/lower.rs4
-rw-r--r--crates/hir/src/semantics.rs12
-rw-r--r--crates/hir/src/source_analyzer.rs9
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<Path> {
- 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<F, T: ast::AstNode>(
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<LocalTypeOrConstParamId, LocalLifetimeParamId>,
@@ -468,7 +468,7 @@ impl GenericParamsCollector {
pub(crate) fn fill_bounds(
&mut self,
- lower_ctx: &LowerCtx<'_>,
+ lower_ctx: &mut LowerCtx<'_>,
type_bounds: Option<ast::TypeBoundList>,
target: Either<TypeRefId, LifetimeRef>,
) {
@@ -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<LocalTypeOrConstParamId, LocalLifetimeParamId>,
@@ -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<TypeRefId, LifetimeRef>,
@@ -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<Self> {
+ pub(crate) fn from_ast(ctx: &mut LowerCtx<'_>, node: ast::Type) -> Option<Self> {
// 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<ast::Type>) -> TypeRefId {
+ pub(crate) fn from_ast_opt(ctx: &mut LowerCtx<'_>, node: Option<ast::Type>) -> 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<ast::TypeBoundList>,
) -> ThinVec<TypeBound> {
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<FileItemTreeId<Struct>> {
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<FileItemTreeId<Union>> {
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<Variant> {
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<FileItemTreeId<Function>> {
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<FileItemTreeId<TypeAlias>> {
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<FileItemTreeId<Static>> {
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<Const> {
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<Impl> {
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<GenericParams>, 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<LocalTypeOrConstParamId, LocalLifetimeParamId>,
- param| {
- let attrs = RawAttrs::new(self.db.upcast(), &param, 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<LocalTypeOrConstParamId, LocalLifetimeParamId>,
+ param| {
+ let attrs = RawAttrs::new(self.db.upcast(), &param, 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<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)
}
}
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<Path> {
+ pub fn from_src(ctx: &mut LowerCtx<'_>, path: ast::Path) -> Option<Path> {
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<GenericArgs> {
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<Path> {
+pub(super) fn lower_path(ctx: &mut LowerCtx<'_>, mut path: ast::Path) -> Option<Path> {
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<Path
if name_ref.text() == "$crate" {
break kind = resolve_crate_root(
ctx.db.upcast(),
- span_map.span_for_range(name_ref.syntax().text_range()).ctx,
+ ctx.span_map().span_for_range(name_ref.syntax().text_range()).ctx,
)
.map(PathKind::DollarCrate)
.unwrap_or(PathKind::Crate);
@@ -151,7 +150,7 @@ pub(super) fn lower_path(ctx: &LowerCtx<'_>, mut path: ast::Path) -> 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) {
- let syn_ctxt = span_map.span_for_range(path.segment()?.syntax().text_range()).ctx;
+ let syn_ctxt = ctx.span_map().span_for_range(path.segment()?.syntax().text_range()).ctx;
if let Some(macro_call_id) = ctx.db.lookup_intern_syntax_context(syn_ctxt).outer_expn {
if ctx.db.lookup_intern_macro_call(macro_call_id).def.local_inner {
kind = match resolve_crate_root(ctx.db.upcast(), syn_ctxt) {
@@ -183,7 +182,7 @@ pub(super) fn lower_path(ctx: &LowerCtx<'_>, mut path: ast::Path) -> Option<Path
}
pub(super) fn lower_generic_args(
- lower_ctx: &LowerCtx<'_>,
+ lower_ctx: &mut LowerCtx<'_>,
node: ast::GenericArgList,
) -> Option<GenericArgs> {
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<Assoc = impl Bar>` 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<ast::ParamList>,
ret_type: Option<ast::RetType>,
) -> Option<GenericArgs> {
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<PathResolution> {
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<Macro> {
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.