diff --git a/crates/stc_ts_file_analyzer/src/analyzer/assign/array.rs b/crates/stc_ts_file_analyzer/src/analyzer/assign/array.rs index 2aff087e1b..f6628dbc4a 100644 --- a/crates/stc_ts_file_analyzer/src/analyzer/assign/array.rs +++ b/crates/stc_ts_file_analyzer/src/analyzer/assign/array.rs @@ -19,7 +19,7 @@ use crate::{ impl Analyzer<'_, '_> { /// Returns `Ok(Some())` if the assignment is handled. pub(super) fn assign_to_tuple( - &mut self, + &self, data: &mut AssignData, l: &Tuple, l_type: &Type, diff --git a/crates/stc_ts_file_analyzer/src/analyzer/assign/builtin.rs b/crates/stc_ts_file_analyzer/src/analyzer/assign/builtin.rs index fbe7788726..94ec6d1a46 100644 --- a/crates/stc_ts_file_analyzer/src/analyzer/assign/builtin.rs +++ b/crates/stc_ts_file_analyzer/src/analyzer/assign/builtin.rs @@ -21,7 +21,7 @@ impl Analyzer<'_, '_> { /// - Handles assignment of `Function` types. /// - Handles assignment of various array types. /// - Handles assignment of promise types. - pub(super) fn assign_to_builtin(&mut self, data: &mut AssignData, l: &Type, r: &Type, opts: AssignOpts) -> Option> { + pub(super) fn assign_to_builtin(&self, data: &mut AssignData, l: &Type, r: &Type, opts: AssignOpts) -> Option> { let span = opts.span; let l = l.normalize(); let r = r.normalize(); diff --git a/crates/stc_ts_file_analyzer/src/analyzer/assign/cast.rs b/crates/stc_ts_file_analyzer/src/analyzer/assign/cast.rs index 736499c977..1da7be4284 100644 --- a/crates/stc_ts_file_analyzer/src/analyzer/assign/cast.rs +++ b/crates/stc_ts_file_analyzer/src/analyzer/assign/cast.rs @@ -9,7 +9,7 @@ use crate::analyzer::{types::NormalizeTypeOpts, Analyzer}; impl Analyzer<'_, '_> { /// Returns true if the type can be casted to number if it's in the rvalue /// position. - pub(crate) fn can_be_casted_to_number_in_rhs(&mut self, span: Span, ty: &Type) -> bool { + pub(crate) fn can_be_casted_to_number_in_rhs(&self, span: Span, ty: &Type) -> bool { let ty = match self.normalize( Some(span), Cow::Borrowed(ty), diff --git a/crates/stc_ts_file_analyzer/src/analyzer/assign/class.rs b/crates/stc_ts_file_analyzer/src/analyzer/assign/class.rs index c6b374a434..40f356252a 100644 --- a/crates/stc_ts_file_analyzer/src/analyzer/assign/class.rs +++ b/crates/stc_ts_file_analyzer/src/analyzer/assign/class.rs @@ -15,7 +15,7 @@ use crate::{ }; impl Analyzer<'_, '_> { - pub(super) fn assign_to_class_def(&mut self, data: &mut AssignData, l: &ClassDef, r: &Type, opts: AssignOpts) -> VResult<()> { + pub(super) fn assign_to_class_def(&self, data: &mut AssignData, l: &ClassDef, r: &Type, opts: AssignOpts) -> VResult<()> { let r = self.normalize(Some(opts.span), Cow::Borrowed(r), Default::default())?; match r.normalize() { @@ -127,7 +127,7 @@ impl Analyzer<'_, '_> { .into()) } - pub(super) fn assign_to_class(&mut self, data: &mut AssignData, l: &Class, r: &Type, opts: AssignOpts) -> VResult<()> { + pub(super) fn assign_to_class(&self, data: &mut AssignData, l: &Class, r: &Type, opts: AssignOpts) -> VResult<()> { // debug_assert!(!span.is_dummy()); let r = self.normalize(Some(opts.span), Cow::Borrowed(r), Default::default())?; @@ -279,7 +279,7 @@ impl Analyzer<'_, '_> { } fn assign_class_members_to_class_member( - &mut self, + &self, data: &mut AssignData, l: &ClassMember, r: &[ClassMember], diff --git a/crates/stc_ts_file_analyzer/src/analyzer/assign/function.rs b/crates/stc_ts_file_analyzer/src/analyzer/assign/function.rs index fe0285e131..5f7b3a8b79 100644 --- a/crates/stc_ts_file_analyzer/src/analyzer/assign/function.rs +++ b/crates/stc_ts_file_analyzer/src/analyzer/assign/function.rs @@ -28,7 +28,7 @@ use crate::{ /// Methods to handle assignment to function types and constructor types. impl Analyzer<'_, '_> { pub(crate) fn assign_to_fn_like( - &mut self, + &self, data: &mut AssignData, is_call: bool, l_type_params: Option<&TypeParamDecl>, @@ -423,7 +423,7 @@ impl Analyzer<'_, '_> { /// a = b; /// b = a; // error /// ``` - pub(super) fn assign_to_function(&mut self, data: &mut AssignData, lt: &Type, l: &Function, r: &Type, opts: AssignOpts) -> VResult<()> { + pub(super) fn assign_to_function(&self, data: &mut AssignData, lt: &Type, l: &Function, r: &Type, opts: AssignOpts) -> VResult<()> { let _tracing = dev_span!("assign_to_function"); let span = opts.span; @@ -530,7 +530,7 @@ impl Analyzer<'_, '_> { /// b18 = a18; // ok /// ``` pub(super) fn assign_to_constructor( - &mut self, + &self, data: &mut AssignData, lt: &Type, l: &Constructor, @@ -668,7 +668,7 @@ impl Analyzer<'_, '_> { /// # Notes /// /// - `string` is assignable to `...args: any[]`. - fn assign_param(&mut self, data: &mut AssignData, l: &FnParam, r: &FnParam, opts: AssignOpts) -> VResult<()> { + fn assign_param(&self, data: &mut AssignData, l: &FnParam, r: &FnParam, opts: AssignOpts) -> VResult<()> { let _tracing = dev_span!("assign_param"); let span = opts.span; @@ -692,7 +692,7 @@ impl Analyzer<'_, '_> { } /// Implementation of `assign_param`. - fn assign_param_type(&mut self, data: &mut AssignData, l: &Type, r: &Type, opts: AssignOpts) -> VResult<()> { + fn assign_param_type(&self, data: &mut AssignData, l: &Type, r: &Type, opts: AssignOpts) -> VResult<()> { let _tracing = dev_span!("assign_param_type"); let span = opts.span; @@ -832,7 +832,7 @@ impl Analyzer<'_, '_> { /// ``` /// /// So, it's an error if `l.params.len() < r.params.len()`. - pub(crate) fn assign_params(&mut self, data: &mut AssignData, l: &[FnParam], r: &[FnParam], opts: AssignOpts) -> VResult<()> { + pub(crate) fn assign_params(&self, data: &mut AssignData, l: &[FnParam], r: &[FnParam], opts: AssignOpts) -> VResult<()> { let _tracing = dev_span!("assign_params"); let span = opts.span; diff --git a/crates/stc_ts_file_analyzer/src/analyzer/assign/mod.rs b/crates/stc_ts_file_analyzer/src/analyzer/assign/mod.rs index 888bb721c0..446a487748 100644 --- a/crates/stc_ts_file_analyzer/src/analyzer/assign/mod.rs +++ b/crates/stc_ts_file_analyzer/src/analyzer/assign/mod.rs @@ -204,7 +204,7 @@ pub struct AssignData { impl Analyzer<'_, '_> { /// Denies `null` and `undefined`. This method does not check for elements /// of union. - pub(crate) fn deny_null_or_undefined(&mut self, span: Span, ty: &Type) -> VResult<()> { + pub(crate) fn deny_null_or_undefined(&self, span: Span, ty: &Type) -> VResult<()> { if ty.is_kwd(TsKeywordTypeKind::TsUndefinedKeyword) { return Err(ErrorKind::ObjectIsPossiblyUndefined { span }.into()); } @@ -217,7 +217,7 @@ impl Analyzer<'_, '_> { } /// Used to validate assignments like `a += b`. - pub(crate) fn assign_with_operator(&mut self, span: Span, op: AssignOp, lhs: &Type, rhs: &Type) -> VResult<()> { + pub(crate) fn assign_with_operator(&self, span: Span, op: AssignOp, lhs: &Type, rhs: &Type) -> VResult<()> { debug_assert_ne!(op, op!("=")); let l = self.normalize( @@ -446,7 +446,7 @@ impl Analyzer<'_, '_> { } /// Assign `right` to `left`. You can just use default for [AssignData]. - pub(crate) fn assign(&mut self, span: Span, data: &mut AssignData, left: &Type, right: &Type) -> VResult<()> { + pub(crate) fn assign(&self, span: Span, data: &mut AssignData, left: &Type, right: &Type) -> VResult<()> { self.assign_with_opts( data, left, @@ -459,7 +459,7 @@ impl Analyzer<'_, '_> { } /// Assign `right` to `left`. You can just use default for [AssignData]. - pub(crate) fn assign_with_opts(&mut self, data: &mut AssignData, left: &Type, right: &Type, opts: AssignOpts) -> VResult<()> { + pub(crate) fn assign_with_opts(&self, data: &mut AssignData, left: &Type, right: &Type, opts: AssignOpts) -> VResult<()> { if self.config.is_builtin { return Ok(()); } @@ -499,7 +499,7 @@ impl Analyzer<'_, '_> { }) } - fn normalize_for_assign<'a>(&mut self, span: Span, ty: &'a Type, opts: AssignOpts) -> VResult> { + fn normalize_for_assign<'a>(&self, span: Span, ty: &'a Type, opts: AssignOpts) -> VResult> { ty.assert_valid(); let ty = ty.normalize(); @@ -560,7 +560,7 @@ impl Analyzer<'_, '_> { Ok(Cow::Borrowed(ty)) } - fn assign_inner(&mut self, data: &mut AssignData, left: &Type, right: &Type, opts: AssignOpts) -> VResult<()> { + fn assign_inner(&self, data: &mut AssignData, left: &Type, right: &Type, opts: AssignOpts) -> VResult<()> { left.assert_valid(); right.assert_valid(); @@ -611,7 +611,7 @@ impl Analyzer<'_, '_> { } /// Assigns, but does not wrap error with [Error::AssignFailed]. - fn assign_without_wrapping(&mut self, data: &mut AssignData, to: &Type, rhs: &Type, opts: AssignOpts) -> VResult<()> { + fn assign_without_wrapping(&self, data: &mut AssignData, to: &Type, rhs: &Type, opts: AssignOpts) -> VResult<()> { let span = opts.span; if !self.config.is_builtin && span.is_dummy() { @@ -2703,7 +2703,7 @@ impl Analyzer<'_, '_> { } /// Should be called only if `to` is not expandable. - pub(super) fn assign_to_intrinsic(&mut self, data: &mut AssignData, to: &StringMapping, r: &Type, opts: AssignOpts) -> VResult<()> { + pub(super) fn assign_to_intrinsic(&self, data: &mut AssignData, to: &StringMapping, r: &Type, opts: AssignOpts) -> VResult<()> { match r.normalize() { Type::Keyword(KeywordType { kind: TsKeywordTypeKind::TsAnyKeyword, @@ -3110,7 +3110,7 @@ impl Analyzer<'_, '_> { Ok(()) } - fn extract_keys(&mut self, span: Span, ty: &Type) -> VResult { + fn extract_keys(&self, span: Span, ty: &Type) -> VResult { (|| -> VResult<_> { let ty = self.normalize( Some(span), @@ -3170,7 +3170,7 @@ impl Analyzer<'_, '_> { /// /// /// Currently only literals and unions are supported for `keys`. - fn assign_keys(&mut self, data: &mut AssignData, keys: &Type, rhs: &Type, opts: AssignOpts) -> VResult<()> { + fn assign_keys(&self, data: &mut AssignData, keys: &Type, rhs: &Type, opts: AssignOpts) -> VResult<()> { let keys = keys.normalize(); let rhs = rhs.normalize(); @@ -3189,7 +3189,7 @@ impl Analyzer<'_, '_> { .context("tried to assign keys") } - fn assign_to_mapped(&mut self, data: &mut AssignData, l: &Mapped, r: &Type, opts: AssignOpts) -> VResult<()> { + fn assign_to_mapped(&self, data: &mut AssignData, l: &Mapped, r: &Type, opts: AssignOpts) -> VResult<()> { let span = opts.span; let mut r = self .normalize(Some(span), Cow::Borrowed(r), NormalizeTypeOpts { ..Default::default() }) @@ -3320,7 +3320,7 @@ impl Analyzer<'_, '_> { /// Returns true for `A | B | | C = A | B` and similar cases. /// /// Should be called iff lhs is a union type. - fn should_use_special_union_assignment(&mut self, span: Span, r: &Type) -> VResult { + fn should_use_special_union_assignment(&self, span: Span, r: &Type) -> VResult { match r.normalize() { Type::Union(..) => return Ok(true), Type::TypeLit(r) => { @@ -3339,7 +3339,7 @@ impl Analyzer<'_, '_> { } /// TODO(kdy1): I'm not sure about this. - fn variance(&mut self, ty: &Conditional) -> VResult { + fn variance(&self, ty: &Conditional) -> VResult { let can_be_covariant = self.is_covariant(&ty.check_type, &ty.true_type)? || self.is_covariant(&ty.check_type, &ty.false_type)?; let can_be_contravariant = @@ -3352,11 +3352,11 @@ impl Analyzer<'_, '_> { } } - fn is_covariant(&mut self, check_type: &Type, output_type: &Type) -> VResult { + fn is_covariant(&self, check_type: &Type, output_type: &Type) -> VResult { Ok(check_type.type_eq(output_type)) } - fn is_contravariant(&mut self, check_type: &Type, output_type: &Type) -> VResult { + fn is_contravariant(&self, check_type: &Type, output_type: &Type) -> VResult { if let Type::Index(Index { ty, .. }) = output_type.normalize() { if output_type.type_eq(&**ty) { return Ok(true); diff --git a/crates/stc_ts_file_analyzer/src/analyzer/assign/tpl.rs b/crates/stc_ts_file_analyzer/src/analyzer/assign/tpl.rs index bc02f629a3..3f3cf9206a 100644 --- a/crates/stc_ts_file_analyzer/src/analyzer/assign/tpl.rs +++ b/crates/stc_ts_file_analyzer/src/analyzer/assign/tpl.rs @@ -27,7 +27,7 @@ impl Analyzer<'_, '_> { /// orders. /// /// After splitting, we can check if each element is assignable. - pub(crate) fn assign_to_tpl(&mut self, data: &mut AssignData, l: &TplType, r_ty: &Type, opts: AssignOpts) -> VResult<()> { + pub(crate) fn assign_to_tpl(&self, data: &mut AssignData, l: &TplType, r_ty: &Type, opts: AssignOpts) -> VResult<()> { let span = opts.span; let r_ty = r_ty.normalize(); @@ -52,7 +52,7 @@ impl Analyzer<'_, '_> { } /// Ported from `isValidTypeForTemplateLiteralPlaceholder` of `tsc` - pub(crate) fn is_valid_type_for_tpl_lit_placeholder(&mut self, span: Span, source: &Type, target: &Type) -> VResult { + pub(crate) fn is_valid_type_for_tpl_lit_placeholder(&self, span: Span, source: &Type, target: &Type) -> VResult { let _tracing = dev_span!( "is_valid_type_for_tpl_lit_placeholder", source = tracing::field::display(&force_dump_type_as_string(source)), diff --git a/crates/stc_ts_file_analyzer/src/analyzer/assign/type_el.rs b/crates/stc_ts_file_analyzer/src/analyzer/assign/type_el.rs index f9c29af448..f2d534652e 100644 --- a/crates/stc_ts_file_analyzer/src/analyzer/assign/type_el.rs +++ b/crates/stc_ts_file_analyzer/src/analyzer/assign/type_el.rs @@ -37,7 +37,7 @@ impl Analyzer<'_, '_> { /// let b: { key: string } = foo; /// ``` pub(crate) fn assign_to_type_elements( - &mut self, + &self, data: &mut AssignData, lhs_span: Span, lhs: &[TypeElement], @@ -951,7 +951,7 @@ impl Analyzer<'_, '_> { Ok(()) } - fn should_report_properties(&mut self, span: Span, lhs: &[TypeElement], rhs: &Type) -> bool { + fn should_report_properties(&self, span: Span, lhs: &[TypeElement], rhs: &Type) -> bool { let type_call_signatures = lhs .iter() .filter_map(|m| match m { @@ -1004,7 +1004,7 @@ impl Analyzer<'_, '_> { true } - pub(super) fn try_assign_using_parent(&mut self, data: &mut AssignData, l: &Type, r: &Type, opts: AssignOpts) -> Option> { + pub(super) fn try_assign_using_parent(&self, data: &mut AssignData, l: &Type, r: &Type, opts: AssignOpts) -> Option> { let span = opts.span; match r.normalize() { @@ -1040,7 +1040,7 @@ impl Analyzer<'_, '_> { } fn handle_assignment_of_type_elements_to_type_elements( - &mut self, + &self, data: &mut AssignData, missing_fields: &mut Vec, unhandled_rhs: &mut Vec, @@ -1174,7 +1174,7 @@ impl Analyzer<'_, '_> { /// b = a // ok /// ``` fn assign_type_elements_to_type_element( - &mut self, + &self, data: &mut AssignData, missing_fields: &mut Vec, unhandled_rhs: &mut Vec, @@ -1627,7 +1627,7 @@ impl Analyzer<'_, '_> { Ok(()) } - pub(crate) fn index_signature_matches(&mut self, span: Span, index_ty: &Type, prop_ty: &Type) -> VResult { + pub(crate) fn index_signature_matches(&self, span: Span, index_ty: &Type, prop_ty: &Type) -> VResult { if (prop_ty.is_num() && index_ty.is_kwd(TsKeywordTypeKind::TsNumberKeyword)) || (prop_ty.is_str() && index_ty.is_kwd(TsKeywordTypeKind::TsStringKeyword)) { diff --git a/crates/stc_ts_file_analyzer/src/analyzer/assign/unions.rs b/crates/stc_ts_file_analyzer/src/analyzer/assign/unions.rs index de04aa7ad0..940d0fba63 100644 --- a/crates/stc_ts_file_analyzer/src/analyzer/assign/unions.rs +++ b/crates/stc_ts_file_analyzer/src/analyzer/assign/unions.rs @@ -26,7 +26,7 @@ impl Analyzer<'_, '_> { /// /// - lhs = `(["a", number] | ["b", number] | ["c", string]);` /// - rhs = `[("b" | "a"), 1];` - pub(super) fn assign_to_union(&mut self, data: &mut AssignData, l: &Type, r: &Type, opts: AssignOpts) -> Option> { + pub(super) fn assign_to_union(&self, data: &mut AssignData, l: &Type, r: &Type, opts: AssignOpts) -> Option> { let r_res = self.flatten_unions_for_assignment(opts.span, Cow::Borrowed(r)); match r_res { @@ -46,7 +46,7 @@ impl Analyzer<'_, '_> { } } - fn flatten_unions_for_assignment(&mut self, span: Span, ty: Cow) -> VResult { + fn flatten_unions_for_assignment(&self, span: Span, ty: Cow) -> VResult { let ty = self.normalize(Some(span), ty, Default::default())?; match ty.normalize() { @@ -81,7 +81,7 @@ impl Analyzer<'_, '_> { } /// TODO(kdy1): Use Cow - fn append_type_element_to_type(&mut self, span: Span, to: &mut Type, el: &TypeElement) -> VResult<()> { + fn append_type_element_to_type(&self, span: Span, to: &mut Type, el: &TypeElement) -> VResult<()> { if let TypeElement::Property(el) = el { if let Some(el_ty) = &el.type_ann { if let Some(ty) = self.expand_union_for_assignment(span, el_ty) { @@ -129,7 +129,7 @@ impl Analyzer<'_, '_> { } /// TODO(kdy1): Use Cow - fn append_tuple_element_to_type(&mut self, span: Span, to: &mut Type, el: &TupleElement) -> VResult<()> { + fn append_tuple_element_to_type(&self, span: Span, to: &mut Type, el: &TupleElement) -> VResult<()> { if let Some(el_ty) = self.expand_union_for_assignment(span, &el.ty) { let mut to_types = (0..el_ty.types.len()).map(|_| to.clone()).collect_vec(); @@ -174,7 +174,7 @@ impl Analyzer<'_, '_> { } /// Expands `boolean` to `true | false`. - fn expand_union_for_assignment(&mut self, span: Span, t: &Type) -> Option { + fn expand_union_for_assignment(&self, span: Span, t: &Type) -> Option { let t = self.normalize(Some(span), Cow::Borrowed(t), Default::default()).ok()?; match t.normalize() { diff --git a/crates/stc_ts_file_analyzer/src/analyzer/class/mod.rs b/crates/stc_ts_file_analyzer/src/analyzer/class/mod.rs index d4c8517fbd..b7fa601936 100644 --- a/crates/stc_ts_file_analyzer/src/analyzer/class/mod.rs +++ b/crates/stc_ts_file_analyzer/src/analyzer/class/mod.rs @@ -347,8 +347,8 @@ impl Analyzer<'_, '_> { if !v.has_valid_super_call { self.storage.report(ErrorKind::SuperNotCalled { span: c.span }.into()); } else { - debug_assert_eq!(self.scope.kind(), ScopeKind::Class); - *self.scope.class.need_super_call.borrow_mut() = true; + debug_assert_eq!(self.scope.borrow().kind(), ScopeKind::Class); + *self.scope.borrow_mut().class.need_super_call.borrow_mut() = true; } for span in v.nested_super_calls { @@ -409,7 +409,7 @@ impl Analyzer<'_, '_> { param.visit_with(&mut visitor); - child.scope.declaring.extend(names.clone()); + child.scope.borrow_mut().declaring.extend(names.clone()); let p: FnParam = { let ctx = Ctx { @@ -423,7 +423,7 @@ impl Analyzer<'_, '_> { ps.push(p); - child.scope.remove_declaring(names); + child.scope.borrow_mut().remove_declaring(names); } if let Some(body) = &c.body { @@ -710,7 +710,7 @@ impl Analyzer<'_, '_> { let key_span = c.key.span(); if c.is_override { - if let Some(super_class) = &self.scope.get_super_class(false) { + if let Some(super_class) = &self.scope.borrow().get_super_class(false) { if self .access_property( key_span, @@ -741,7 +741,7 @@ impl Analyzer<'_, '_> { child.ctx.in_static_method = c.is_static; child.ctx.is_fn_param = true; - child.scope.declaring_prop = match &key { + child.scope.borrow_mut().declaring_prop = match &key { Key::Normal { sym, .. } => Some(Id::word(sym.clone())), _ => None, }; @@ -790,13 +790,13 @@ impl Analyzer<'_, '_> { } let params = { - let prev_len = child.scope.declaring_parameters.len(); + let prev_len = child.scope.borrow().declaring_parameters.len(); let ids: Vec = find_ids_in_pat(&c.function.params); - child.scope.declaring_parameters.extend(ids); + child.scope.borrow_mut().declaring_parameters.extend(ids); let res = c.function.params.validate_with(child); - child.scope.declaring_parameters.truncate(prev_len); + child.scope.borrow_mut().declaring_parameters.truncate(prev_len); res? }; @@ -814,7 +814,7 @@ impl Analyzer<'_, '_> { let declared_ret_ty = try_opt!(c.function.return_type.validate_with(child)); let declared_ret_ty = declared_ret_ty.map(|ty| ty.freezed()); - child.scope.declared_return_type = declared_ret_ty.clone(); + child.scope.borrow_mut().declared_return_type = declared_ret_ty.clone(); let span = c.function.span; let is_async = c.function.is_async; @@ -1654,7 +1654,7 @@ impl Analyzer<'_, '_> { }; c.decorators.visit_with(self); - let name = self.scope.this_class_name.take(); + let name = self.scope.borrow_mut().this_class_name.take(); if let Some(i) = &name { match &**i.sym() { "any" | "void" | "never" | "string" | "number" | "boolean" | "null" | "undefined" | "symbol" => { @@ -1681,7 +1681,7 @@ impl Analyzer<'_, '_> { child.ctx.super_references_super_class = true; child.ctx.in_class_with_super = c.super_class.is_some(); - child.scope.declaring_type_params.extend( + child.scope.borrow_mut().declaring_type_params.extend( c.type_params .iter() .flat_map(|decl| &decl.params) @@ -1689,7 +1689,7 @@ impl Analyzer<'_, '_> { ); // Register the class. - child.scope.this_class_name = name.clone(); + child.scope.borrow_mut().this_class_name = name.clone(); // We handle type parameters first. let type_params = try_opt!(c.type_params.validate_with(child)).map(Box::new); @@ -1853,7 +1853,7 @@ impl Analyzer<'_, '_> { child.report_errors_for_statics_mixed_with_instances(c).report(&mut child.storage); child.report_errors_for_duplicate_class_members(c).report(&mut child.storage); - child.scope.super_class = super_class.clone(); + child.scope.borrow_mut().super_class = super_class.clone(); { // Validate constructors let constructors_with_body = c @@ -1897,7 +1897,7 @@ impl Analyzer<'_, '_> { if let RClassMember::TsIndexSignature(..) = node { let m = node.validate_with_args(child, type_ann)?; if let Some(member) = m { - child.scope.this_class_members.push((index, member)); + child.scope.borrow_mut().this_class_members.push((index, member)); } } } @@ -1920,7 +1920,7 @@ impl Analyzer<'_, '_> { } let member = member.fold_with(&mut LitGeneralizer {}); - child.scope.this_class_members.push((index, member)); + child.scope.borrow_mut().this_class_members.push((index, member)); } } _ => {} @@ -2004,7 +2004,7 @@ impl Analyzer<'_, '_> { } // Register a class property. - child.scope.this_class_members.push(( + child.scope.borrow_mut().this_class_members.push(( index, ClassMember::Property(stc_ts_types::ClassProperty { span: p.span, @@ -2047,7 +2047,7 @@ impl Analyzer<'_, '_> { } let member = member.fold_with(&mut LitGeneralizer); - child.scope.this_class_members.push((index, member)); + child.scope.borrow_mut().this_class_members.push((index, member)); } } _ => {} @@ -2067,7 +2067,7 @@ impl Analyzer<'_, '_> { } else { cons_with_body = Some(member.clone()); } - child.scope.this_class_members.push((index, member.into())); + child.scope.borrow_mut().this_class_members.push((index, member.into())); } child .report_errors_for_wrong_constructor_overloads(&ambient_cons, cons_with_body.as_ref()) @@ -2090,7 +2090,7 @@ impl Analyzer<'_, '_> { .body .iter() .enumerate() - .filter(|(index, _)| child.scope.this_class_members.iter().all(|(idx, _)| *idx != *index)) + .filter(|(index, _)| child.scope.borrow().this_class_members.iter().all(|(idx, _)| *idx != *index)) .map(|v| v.0) .collect::>(); @@ -2099,11 +2099,11 @@ impl Analyzer<'_, '_> { for index in order { let ty = c.body[index].validate_with_args(child, type_ann)?; if let Some(ty) = ty { - child.scope.this_class_members.push((index, ty)); + child.scope.borrow_mut().this_class_members.push((index, ty)); } } - take(&mut child.scope.this_class_members) + take(&mut child.scope.borrow_mut().this_class_members) }; let body = child.combine_class_properties(body); @@ -2156,7 +2156,7 @@ impl Analyzer<'_, '_> { #[validator] impl Analyzer<'_, '_> { fn validate(&mut self, c: &RClassExpr, type_ann: Option<&Type>) -> VResult<()> { - self.scope.this_class_name = c.ident.as_ref().map(|v| v.into()); + self.scope.get_mut().this_class_name = c.ident.as_ref().map(|v| v.into()); let ty = match c.class.validate_with_args(self, type_ann) { Ok(ty) => ty.into(), Err(err) => { @@ -2165,7 +2165,7 @@ impl Analyzer<'_, '_> { } }; - let old_this = self.scope.this.take(); + let old_this = self.scope.borrow_mut().this.take(); // self.scope.this = Some(ty.clone()); let c = self @@ -2199,7 +2199,7 @@ impl Analyzer<'_, '_> { }) .report(&mut self.storage); - self.scope.this = old_this; + self.scope.borrow_mut().this = old_this; Ok(()) } @@ -2389,7 +2389,7 @@ impl Analyzer<'_, '_> { .. }) = ty.normalize() { - if let Some(name) = &self.scope.this_class_name { + if let Some(name) = &self.scope.borrow().this_class_name { if *name == i { Err(ErrorKind::SelfReferentialSuperClass { span: i.span })? } @@ -2407,7 +2407,7 @@ impl Analyzer<'_, '_> { } /// TODO(kdy1): Instantiate fully - pub(crate) fn instantiate_class(&mut self, span: Span, ty: &Type) -> VResult { + pub(crate) fn instantiate_class(&self, span: Span, ty: &Type) -> VResult { let span = span.with_ctxt(SyntaxContext::empty()); Ok(match ty.normalize() { @@ -2424,7 +2424,7 @@ impl Analyzer<'_, '_> { fn visit_class_decl_inner(&mut self, c: &RClassDecl) { c.ident.visit_with(self); - self.scope.this_class_name = Some(c.ident.clone().into()); + self.scope.borrow_mut().this_class_name = Some(c.ident.clone().into()); let ty = match c.class.validate_with_args(self, None) { Ok(ty) => ty.into(), Err(err) => { @@ -2434,7 +2434,7 @@ impl Analyzer<'_, '_> { }; let ty = ty.freezed(); - let old_this = self.scope.this.take(); + let old_this = self.scope.borrow_mut().this.take(); // self.scope.this = Some(ty.clone()); let ty = self.register_type(c.ident.clone().into(), ty); @@ -2458,7 +2458,7 @@ impl Analyzer<'_, '_> { } } - self.scope.this = old_this; + self.scope.borrow_mut().this = old_this; } } diff --git a/crates/stc_ts_file_analyzer/src/analyzer/class/type_param.rs b/crates/stc_ts_file_analyzer/src/analyzer/class/type_param.rs index ccfceea037..c4ba7adf6b 100644 --- a/crates/stc_ts_file_analyzer/src/analyzer/class/type_param.rs +++ b/crates/stc_ts_file_analyzer/src/analyzer/class/type_param.rs @@ -6,8 +6,9 @@ use swc_common::Span; use crate::analyzer::{Analyzer, ScopeKind}; impl Analyzer<'_, '_> { - pub(crate) fn is_type_param_declared_in_containing_class(&mut self, id: &Id) -> bool { + pub(crate) fn is_type_param_declared_in_containing_class(&self, id: &Id) -> bool { self.scope + .borrow() .first(|scope| { let parent = scope.parent(); let parent = match parent { diff --git a/crates/stc_ts_file_analyzer/src/analyzer/control_flow.rs b/crates/stc_ts_file_analyzer/src/analyzer/control_flow.rs index 74f6d53624..e307de6ebe 100644 --- a/crates/stc_ts_file_analyzer/src/analyzer/control_flow.rs +++ b/crates/stc_ts_file_analyzer/src/analyzer/control_flow.rs @@ -765,7 +765,7 @@ impl Analyzer<'_, '_> { if let Ok(prev) = self.type_of_var(left, TypeOfMode::RValue, None) { let new_actual_ty = self.apply_type_facts_to_type(TypeFacts::NEUndefinedOrNull, prev); - if let Some(var) = self.scope.vars.get_mut(&Id::from(left)) { + if let Some(var) = self.scope.borrow_mut().vars.get_mut(&Id::from(left)) { var.actual_ty = Some(new_actual_ty.freezed()); } } @@ -838,7 +838,7 @@ impl Analyzer<'_, '_> { let span = span.with_ctxt(SyntaxContext::empty()); - let is_in_loop = self.scope.is_in_loop_body(); + let is_in_loop = self.scope.borrow().is_in_loop_body(); let ctx = Ctx { in_actual_type: true, @@ -884,7 +884,7 @@ impl Analyzer<'_, '_> { RPat::Ident(i) => { // Verify using immutable references. - if let Some(var_info) = self.scope.get_var(&i.id.clone().into()) { + if let Some(var_info) = self.scope.borrow().get_var(&i.id.clone().into()) { if let Some(mut var_ty) = var_info.ty.clone() { var_ty.freeze(); @@ -902,10 +902,12 @@ impl Analyzer<'_, '_> { } let mut actual_ty = None; + let b = self.scope.borrow(); if let Some(var_info) = self .scope + .borrow() .get_var(&i.id.clone().into()) - .or_else(|| self.scope.search_parent(&i.id.clone().into())) + .or_else(|| b.search_parent(&i.id.clone().into())) { if let Some(declared_ty) = &var_info.ty { declared_ty.assert_valid(); @@ -952,7 +954,7 @@ impl Analyzer<'_, '_> { } // Update actual types. - if let Some(var_info) = self.scope.get_var_mut(&i.id.clone().into()) { + if let Some(var_info) = self.scope.borrow_mut().get_var_mut(&i.id.clone().into()) { var_info.is_actual_type_modified_in_loop |= is_in_loop; let mut new_ty = actual_ty.unwrap_or_else(|| ty.clone()); new_ty.assert_valid(); @@ -961,7 +963,7 @@ impl Analyzer<'_, '_> { return Ok(()); } - let var_info = if let Some(var_info) = self.scope.search_parent(&i.id.clone().into()) { + let var_info = if let Some(var_info) = self.scope.borrow().search_parent(&i.id.clone().into()) { let actual_ty = actual_ty.unwrap_or_else(|| orig_ty.clone()); actual_ty.assert_valid(); actual_ty.assert_clone_cheap(); @@ -985,7 +987,7 @@ impl Analyzer<'_, '_> { } } - return if self.ctx.allow_ref_declaring && self.scope.declaring.contains(&i.id.clone().into()) { + return if self.ctx.allow_ref_declaring && self.scope.borrow().declaring.contains(&i.id.clone().into()) { Ok(()) } else { // undefined symbol @@ -1000,7 +1002,7 @@ impl Analyzer<'_, '_> { // Variable is defined on parent scope. // // We copy var info with enhanced type. - self.scope.insert_var(i.id.clone().into(), var_info); + self.scope.borrow_mut().insert_var(i.id.clone().into(), var_info); Ok(()) } diff --git a/crates/stc_ts_file_analyzer/src/analyzer/convert/mod.rs b/crates/stc_ts_file_analyzer/src/analyzer/convert/mod.rs index db0b0ca084..aa0d7286a8 100644 --- a/crates/stc_ts_file_analyzer/src/analyzer/convert/mod.rs +++ b/crates/stc_ts_file_analyzer/src/analyzer/convert/mod.rs @@ -874,7 +874,7 @@ impl Analyzer<'_, '_> { } if !self.config.is_builtin && !found && self.ctx.in_actual_type { - if self.scope.get_var(&i.into()).is_some() { + if self.scope.borrow().get_var(&i.into()).is_some() { self.storage .report(ErrorKind::NoSuchTypeButVarExists { span, name: i.into() }.into()); reported_type_not_found = true; @@ -882,7 +882,7 @@ impl Analyzer<'_, '_> { } } else { if !self.config.is_builtin && self.ctx.in_actual_type { - if self.scope.get_var(&i.into()).is_some() { + if self.scope.borrow().get_var(&i.into()).is_some() { self.storage .report(ErrorKind::NoSuchTypeButVarExists { span, name: i.into() }.into()); reported_type_not_found = true; @@ -1288,7 +1288,8 @@ impl Analyzer<'_, '_> { let span = i.span; let id = i.into(); - let static_method = self.scope.first(|scope| { + let b = self.scope.borrow(); + let static_method = b.first(|scope| { let parent = scope.parent(); let parent = match parent { Some(v) => v, diff --git a/crates/stc_ts_file_analyzer/src/analyzer/enums.rs b/crates/stc_ts_file_analyzer/src/analyzer/enums.rs index a3bf982750..244bd70689 100644 --- a/crates/stc_ts_file_analyzer/src/analyzer/enums.rs +++ b/crates/stc_ts_file_analyzer/src/analyzer/enums.rs @@ -383,7 +383,7 @@ impl Analyzer<'_, '_> { /// }; /// var e: typeof E1; /// ``` - pub(super) fn enum_to_type_lit(&mut self, e: &ArcCow) -> VResult { + pub(super) fn enum_to_type_lit(&self, e: &ArcCow) -> VResult { let mut members = vec![]; for m in &e.members { diff --git a/crates/stc_ts_file_analyzer/src/analyzer/export.rs b/crates/stc_ts_file_analyzer/src/analyzer/export.rs index 2d3d611cc3..af03222351 100644 --- a/crates/stc_ts_file_analyzer/src/analyzer/export.rs +++ b/crates/stc_ts_file_analyzer/src/analyzer/export.rs @@ -135,7 +135,7 @@ impl Analyzer<'_, '_> { let id: Option = c.ident.as_ref().map(|v| v.into()); let orig_name = id.clone(); - self.scope.this_class_name = id.clone(); + self.scope.borrow_mut().this_class_name = id.clone(); let var_name = id.unwrap_or_else(|| Id::word(js_word!("default"))); diff --git a/crates/stc_ts_file_analyzer/src/analyzer/expr/array.rs b/crates/stc_ts_file_analyzer/src/analyzer/expr/array.rs index 53d4585e3f..0aba9890a8 100644 --- a/crates/stc_ts_file_analyzer/src/analyzer/expr/array.rs +++ b/crates/stc_ts_file_analyzer/src/analyzer/expr/array.rs @@ -246,7 +246,7 @@ impl Analyzer<'_, '_> { impl Analyzer<'_, '_> { /// Get `n`th element from the `iterator`. - pub(crate) fn get_element_from_iterator<'a>(&mut self, span: Span, iterator: Cow<'a, Type>, n: usize) -> VResult> { + pub(crate) fn get_element_from_iterator<'a>(&self, span: Span, iterator: Cow<'a, Type>, n: usize) -> VResult> { debug!("Calculating element type of an iterator ({})", dump_type_as_string(&iterator)); if iterator.is_any() { @@ -382,7 +382,7 @@ impl Analyzer<'_, '_> { Ok(Cow::Owned(value_ty)) } - fn try_next_method_of_iterator(&mut self, span: Span, iterator: &Type, awaited: bool) -> VResult { + fn try_next_method_of_iterator(&self, span: Span, iterator: &Type, awaited: bool) -> VResult { let _tracing = dev_span!("try_next_method_of_iterator"); let mut item = self @@ -417,7 +417,7 @@ impl Analyzer<'_, '_> { } pub(crate) fn get_async_iterator_element_type<'a>( - &mut self, + &self, span: Span, ty: Cow<'a, Type>, try_next_method: bool, @@ -432,7 +432,7 @@ impl Analyzer<'_, '_> { if !self.data.checked_for_async_iterator { self.data.checked_for_async_iterator = true; - self.env.get_global_type(span, &"AsyncIterator".into()).report(&mut self.storage); + self.env.get_global_type(span, &"AsyncIterator".into()).report(&self.storage); } if let Ok(item) = self.try_next_method_of_iterator(span, &ty, true) { @@ -490,7 +490,7 @@ impl Analyzer<'_, '_> { Ok(Cow::Owned(elem_ty.into_owned())) } - pub(crate) fn get_value_type_from_iterator_result(&mut self, span: Span, iterator_result: &Type) -> VResult { + pub(crate) fn get_value_type_from_iterator_result(&self, span: Span, iterator_result: &Type) -> VResult { let iterator_result = self.normalize( Some(span), Cow::Borrowed(iterator_result), @@ -555,12 +555,7 @@ impl Analyzer<'_, '_> { Ok(elem_ty) } - pub(crate) fn get_rest_elements<'a>( - &mut self, - span: Option, - iterator: Cow<'a, Type>, - start_index: usize, - ) -> VResult> { + pub(crate) fn get_rest_elements<'a>(&self, span: Option, iterator: Cow<'a, Type>, start_index: usize) -> VResult> { let mut iterator = self.normalize(span, iterator, NormalizeTypeOpts { ..Default::default() })?; if iterator.is_tuple() { @@ -592,7 +587,7 @@ impl Analyzer<'_, '_> { Ok(Cow::Owned(iterator.into_owned())) } - pub(crate) fn get_iterator<'a>(&mut self, span: Span, ty: Cow<'a, Type>, opts: GetIteratorOpts) -> VResult> { + pub(crate) fn get_iterator<'a>(&self, span: Span, ty: Cow<'a, Type>, opts: GetIteratorOpts) -> VResult> { let start = Instant::now(); let iterator = self.get_iterator_inner(span, ty, opts).context("tried to get iterator"); @@ -623,7 +618,7 @@ impl Analyzer<'_, '_> { Ok(iterator) } - fn get_iterator_inner<'a>(&mut self, span: Span, ty: Cow<'a, Type>, opts: GetIteratorOpts) -> VResult> { + fn get_iterator_inner<'a>(&self, span: Span, ty: Cow<'a, Type>, opts: GetIteratorOpts) -> VResult> { let ty_str = force_dump_type_as_string(&ty); debug!("[exprs/array] get_iterator({})", ty_str); ty.assert_valid(); @@ -768,7 +763,7 @@ impl Analyzer<'_, '_> { /// /// If it's true, this method will try `ty.next().value`. pub(crate) fn get_iterator_element_type<'a>( - &mut self, + &self, span: Span, ty: Cow<'a, Type>, try_next_value: bool, @@ -874,7 +869,7 @@ impl Analyzer<'_, '_> { } /// Returns the type of `iterator.next().value`. - fn get_next_value_type_of_iterator(&mut self, span: Span, iterator: Cow) -> VResult { + fn get_next_value_type_of_iterator(&self, span: Span, iterator: Cow) -> VResult { let next_ret_ty = self .call_property( span, @@ -909,7 +904,7 @@ impl Analyzer<'_, '_> { Ok(elem_ty) } - pub(crate) fn calculate_tuple_element_count(&mut self, span: Span, ty: &Type) -> VResult> { + pub(crate) fn calculate_tuple_element_count(&self, span: Span, ty: &Type) -> VResult> { let ty = self.normalize( Some(span), Cow::Borrowed(ty), diff --git a/crates/stc_ts_file_analyzer/src/analyzer/expr/await_expr.rs b/crates/stc_ts_file_analyzer/src/analyzer/expr/await_expr.rs index b5ff09187e..6471ae20a8 100644 --- a/crates/stc_ts_file_analyzer/src/analyzer/expr/await_expr.rs +++ b/crates/stc_ts_file_analyzer/src/analyzer/expr/await_expr.rs @@ -76,7 +76,7 @@ impl Analyzer<'_, '_> { } impl Analyzer<'_, '_> { - pub(crate) fn get_awaited_type<'a>(&mut self, span: Span, ty: Cow<'a, Type>, error_on_missing_then: bool) -> VResult> { + pub(crate) fn get_awaited_type<'a>(&self, span: Span, ty: Cow<'a, Type>, error_on_missing_then: bool) -> VResult> { if let Some(arg) = unwrap_builtin_with_single_arg(&ty, "Promise").or_else(|| unwrap_builtin_with_single_arg(&ty, "PromiseLike")) { return self .get_awaited_type(span, Cow::Borrowed(arg), false) diff --git a/crates/stc_ts_file_analyzer/src/analyzer/expr/call_new.rs b/crates/stc_ts_file_analyzer/src/analyzer/expr/call_new.rs index dc1be12f10..6f7ab6131d 100644 --- a/crates/stc_ts_file_analyzer/src/analyzer/expr/call_new.rs +++ b/crates/stc_ts_file_analyzer/src/analyzer/expr/call_new.rs @@ -106,7 +106,7 @@ impl Analyzer<'_, '_> { self.validate_args(args).report(&mut self.storage); - self.scope.mark_as_super_called(); + self.scope.borrow_mut().mark_as_super_called(); return Ok(Type::any(span, Default::default())); } @@ -298,7 +298,7 @@ impl Analyzer<'_, '_> { ) -> VResult { let _tracing = dev_span!("extract_call_new_expr_member"); - debug_assert_eq!(self.scope.kind(), ScopeKind::Call); + debug_assert_eq!(self.scope.borrow().kind(), ScopeKind::Call); let marks = self.marks(); @@ -608,8 +608,8 @@ impl Analyzer<'_, '_> { let span = span.with_ctxt(SyntaxContext::empty()); - let old_this = self.scope.this.take(); - self.scope.this = Some(this.clone()); + let old_this = self.scope.borrow_mut().this.take(); + self.scope.borrow_mut().this = Some(this.clone()); let res = (|| { let obj_type = self @@ -968,7 +968,7 @@ impl Analyzer<'_, '_> { }) })() .with_context(|| format!("tried to call a property of an object ({})", force_dump_type_as_string(obj_type))); - self.scope.this = old_this; + self.scope.borrow_mut().this = old_this; res } @@ -1130,7 +1130,7 @@ impl Analyzer<'_, '_> { } fn check_type_element_for_call( - &mut self, + &self, span: Span, kind: ExtractKind, candidates: &mut Vec, @@ -1341,7 +1341,7 @@ impl Analyzer<'_, '_> { kind: TsKeywordTypeKind::TsAnyKeyword, .. }) => { - self.scope.is_call_arg_count_unknown = true; + self.scope.borrow_mut().is_call_arg_count_unknown = true; new_arg_types.push(TypeOrSpread { span: *span, spread: None, @@ -1350,7 +1350,7 @@ impl Analyzer<'_, '_> { } Type::Array(arr) => { - self.scope.is_call_arg_count_unknown = true; + self.scope.borrow_mut().is_call_arg_count_unknown = true; new_arg_types.push(arg.clone()); } @@ -1359,7 +1359,7 @@ impl Analyzer<'_, '_> { } _ => { - self.scope.is_call_arg_count_unknown = true; + self.scope.borrow_mut().is_call_arg_count_unknown = true; let elem_type = self .get_iterator_element_type(arg.span(), arg_ty, false, Default::default()) @@ -1431,7 +1431,7 @@ impl Analyzer<'_, '_> { if let ExtractKind::New = kind { match ty.normalize() { Type::ClassDef(ref cls) => { - self.scope.this = Some(Type::Class(Class { + self.scope.borrow_mut().this = Some(Type::Class(Class { span, def: cls.clone(), metadata: Default::default(), @@ -1629,7 +1629,7 @@ impl Analyzer<'_, '_> { } Type::StaticThis(..) => { - if let Some(class_name) = self.scope.this_class_name() { + if let Some(class_name) = self.scope.borrow().this_class_name() { return Ok(Type::Instance(Instance { span, ty: Box::new(Type::Query(QueryType { @@ -2045,7 +2045,7 @@ impl Analyzer<'_, '_> { ) } - pub(super) fn extract_callee_candidates(&mut self, span: Span, kind: ExtractKind, callee: &Type) -> VResult> { + pub(super) fn extract_callee_candidates(&self, span: Span, kind: ExtractKind, callee: &Type) -> VResult> { let span = span.with_ctxt(SyntaxContext::empty()); let callee = self @@ -2764,7 +2764,7 @@ impl Analyzer<'_, '_> { if let Some(type_params) = type_params { for param in type_params { - info!("({}) Defining {}", self.scope.depth(), param.name); + info!("({}) Defining {}", self.scope.borrow().depth(), param.name); self.register_type(param.name.clone(), Type::Param(param.clone())); } @@ -3768,7 +3768,7 @@ impl Analyzer<'_, '_> { } } - if analyzer.scope.is_call_arg_count_unknown || !exact { + if analyzer.scope.borrow().is_call_arg_count_unknown || !exact { return ArgCheckResult::MayBe; } ArgCheckResult::Exact diff --git a/crates/stc_ts_file_analyzer/src/analyzer/expr/mod.rs b/crates/stc_ts_file_analyzer/src/analyzer/expr/mod.rs index e61b3fbce4..4b91c54f35 100644 --- a/crates/stc_ts_file_analyzer/src/analyzer/expr/mod.rs +++ b/crates/stc_ts_file_analyzer/src/analyzer/expr/mod.rs @@ -162,19 +162,22 @@ impl Analyzer<'_, '_> { self.storage.report(ErrorKind::ThisInConstructorParam { span }.into()) } - if self.scope.cannot_use_this_because_super_not_called() { + if self.scope.borrow().cannot_use_this_because_super_not_called() { self.storage.report(ErrorKind::ThisUsedBeforeCallingSuper { span }.into()) } - let is_ref_to_module = matches!(self.scope.kind(), ScopeKind::Module) + let is_ref_to_module = matches!(self.scope.borrow().kind(), ScopeKind::Module) || (self.ctx.in_computed_prop_name - && matches!(self.scope.scope_of_computed_props().map(|s| s.kind()), Some(ScopeKind::Module))); + && matches!( + self.scope.borrow().scope_of_computed_props().map(|s| s.kind()), + Some(ScopeKind::Module) + )); if is_ref_to_module { self.storage.report(ErrorKind::ThisRefToModuleOrNamespace { span }.into()) } // Use globalThis - if !self.scope.is_this_defined() { + if !self.scope.borrow().is_this_defined() { return Ok(Type::Query(QueryType { span, expr: Box::new(QueryExpr::TsEntityName(RTsEntityName::Ident(RIdent::new( @@ -186,10 +189,11 @@ impl Analyzer<'_, '_> { })); } + let b = self.scope.borrow(); let scope = if self.ctx.in_computed_prop_name { - self.scope.scope_of_computed_props() + b.scope_of_computed_props() } else { - Some(&self.scope) + Some(&*b) }; if let Some(scope) = scope { if let Some(ty) = scope.this() { @@ -256,7 +260,7 @@ impl Analyzer<'_, '_> { RExpr::Await(e) => e.validate_with_args(self, type_ann.as_deref()), RExpr::Class(RClassExpr { ref ident, ref class, .. }) => { - self.scope.this_class_name = ident.as_ref().map(|i| i.into()); + self.scope.borrow_mut().this_class_name = ident.as_ref().map(|i| i.into()); Ok(class.validate_with_args(self, type_ann.as_deref())?.into()) } @@ -376,7 +380,7 @@ impl Analyzer<'_, '_> { let (any_span, type_ann) = match e.left { RPatOrExpr::Pat(box RPat::Ident(RBindingIdent { id: ref i, .. })) | RPatOrExpr::Expr(box RExpr::Ident(ref i)) => { // Type is any if self.declaring contains ident - let any_span = if analyzer.scope.declaring.contains(&i.into()) { + let any_span = if analyzer.scope.borrow().declaring.contains(&i.into()) { Some(span) } else { None @@ -513,7 +517,7 @@ impl Analyzer<'_, '_> { if let Some(stc_ts_types::Function { params, .. }) = ty.as_fn_type_mut() { if !rhs_is_arrow { if !left_function_declare_not_this_type { - analyzer.scope.this = Some(*params[0].ty.to_owned()); + analyzer.scope.borrow_mut().this = Some(*params[0].ty.to_owned()); } else { // bound this (lhs to rhs) if let RPatOrExpr::Pat(box RPat::Expr(box RExpr::Member(RMemberExpr { @@ -525,7 +529,7 @@ impl Analyzer<'_, '_> { .type_of_var(obj, TypeOfMode::LValue, None) .context("tried to get type of lhs of an assignment") { - analyzer.scope.this = Some(value); + analyzer.scope.borrow_mut().this = Some(value); } } } @@ -551,7 +555,7 @@ impl Analyzer<'_, '_> { Some(ty) if right_function_declared_this => { let mut ty = ty.clone(); if let Some(stc_ts_types::Function { params, .. }) = ty.as_fn_type_mut() { - if let Some(this) = &analyzer.scope.this { + if let Some(this) = &analyzer.scope.borrow().this { params[0] = FnParam { ty: Box::new( Type::Instance(Instance { @@ -727,7 +731,7 @@ impl Analyzer<'_, '_> { } } if let RExpr::Ident(ref i) = **e { - if self.scope.declaring.contains(&i.into()) { + if self.scope.borrow().declaring.contains(&i.into()) { is_any = true; } } @@ -823,7 +827,7 @@ impl Analyzer<'_, '_> { /// # Parameters /// /// - `declared`: Key of declared property. - pub(crate) fn key_matches(&mut self, span: Span, declared: &Key, cur: &Key, allow_union: bool) -> bool { + pub(crate) fn key_matches(&self, span: Span, declared: &Key, cur: &Key, allow_union: bool) -> bool { let _tracing = dev_span!("key_matches"); match declared { @@ -907,7 +911,7 @@ impl Analyzer<'_, '_> { .is_ok() } - fn check_if_type_matches_key(&mut self, span: Span, declared: &Key, key_ty: &Type, allow_union: bool) -> bool { + fn check_if_type_matches_key(&self, span: Span, declared: &Key, key_ty: &Type, allow_union: bool) -> bool { let key_ty = key_ty.normalize(); if declared.ty().type_eq(key_ty) { @@ -953,7 +957,7 @@ impl Analyzer<'_, '_> { } fn access_property_of_type_elements( - &mut self, + &self, span: Span, obj: &Type, prop: &Key, @@ -1207,7 +1211,7 @@ impl Analyzer<'_, '_> { } pub(super) fn access_property( - &mut self, + &self, span: Span, obj: &Type, prop: &Key, @@ -1386,7 +1390,7 @@ impl Analyzer<'_, '_> { } fn access_property_inner( - &mut self, + &self, span: Span, obj: &Type, prop: &Key, @@ -1570,9 +1574,9 @@ impl Analyzer<'_, '_> { Type::This(..) | Type::StaticThis(..) => { if !computed && !self.ctx.in_computed_prop_name - && (self.scope.is_this_ref_to_object_lit() || self.scope.is_this_ref_to_class()) + && (self.scope.borrow().is_this_ref_to_object_lit() || self.scope.borrow().is_this_ref_to_class()) { - if let Some(declaring) = &self.scope.declaring_prop() { + if let Some(declaring) = &self.scope.borrow().declaring_prop() { if prop == declaring.sym() { return Ok(Type::any(span, Default::default())); } @@ -1586,7 +1590,7 @@ impl Analyzer<'_, '_> { Type::This(..) | Type::StaticThis(..) if self.ctx.is_static() => { // Handle static access to class itself while *declaring* the class. #[allow(clippy::unnecessary_to_owned)] - for (_, member) in self.scope.class_members().to_vec() { + for (_, member) in self.scope.borrow().class_members().to_vec() { match member { ClassMember::Method(member @ Method { is_static: true, .. }) => { if self.key_matches(span, &member.key, prop, false) { @@ -1614,7 +1618,7 @@ impl Analyzer<'_, '_> { } } - if let Some(super_class) = self.scope.get_super_class(true) { + if let Some(super_class) = self.scope.borrow().get_super_class(true) { if let Ok(v) = self.access_property(span, &super_class, prop, type_mode, IdCtx::Var, opts) { return Ok(v); } @@ -1628,14 +1632,14 @@ impl Analyzer<'_, '_> { .context("tried to access this in a static class member")); } - Type::This(this) if !self.ctx.in_computed_prop_name && self.scope.is_this_ref_to_object_lit() => { + Type::This(this) if !self.ctx.in_computed_prop_name && self.scope.borrow().is_this_ref_to_object_lit() => { if let Key::Computed(prop) = prop { // return Ok(Type::any(span, Default::default())); } // TODO(kdy1): Remove clone - let members = self.scope.object_lit_members().to_vec(); + let members = self.scope.borrow().object_lit_members().to_vec(); if let Some(mut v) = self.access_property_of_type_elements(span, obj, prop, type_mode, &members, opts)? { v.metadata_mut().infected_by_this_in_object_literal = true; return Ok(v); @@ -1644,10 +1648,10 @@ impl Analyzer<'_, '_> { return Ok(Type::any(span, Default::default())); } - Type::This(this) if !self.ctx.in_computed_prop_name && self.scope.is_this_ref_to_class() => { + Type::This(this) if !self.ctx.in_computed_prop_name && self.scope.borrow().is_this_ref_to_class() => { // We are currently declaring a class. #[allow(clippy::unnecessary_to_owned)] - for (_, member) in self.scope.class_members().to_vec() { + for (_, member) in self.scope.borrow().class_members().to_vec() { match &member { // No-op, as constructor parameter properties are handled by // Validate. @@ -1700,7 +1704,7 @@ impl Analyzer<'_, '_> { } } - if let Some(super_class) = self.scope.get_super_class(false) { + if let Some(super_class) = self.scope.borrow().get_super_class(false) { if let Ok(v) = self.access_property(span, &super_class, prop, type_mode, IdCtx::Var, opts) { return Ok(v); } @@ -1709,13 +1713,13 @@ impl Analyzer<'_, '_> { if !computed { return Err(ErrorKind::NoSuchPropertyInClass { span, - class_name: self.scope.get_this_class_name(), + class_name: self.scope.borrow().get_this_class_name(), prop: prop.clone(), } .context("tried to access this in class")); } - if let Some(super_class) = self.scope.get_super_class(false) { + if let Some(super_class) = self.scope.borrow().get_super_class(false) { if let Ok(v) = self.access_property(span, &super_class, prop, type_mode, IdCtx::Var, opts) { return Ok(v); } @@ -1741,7 +1745,7 @@ impl Analyzer<'_, '_> { Type::StaticThis(StaticThis { span, metadata, .. }) => { // Handle static access to class itself while *declaring* the class. #[allow(clippy::unnecessary_to_owned)] - for (_, member) in self.scope.class_members().to_vec() { + for (_, member) in self.scope.borrow().class_members().to_vec() { match member { ClassMember::Method(member @ Method { is_static: true, .. }) => { if self.key_matches(*span, &member.key, prop, false) { @@ -1774,7 +1778,7 @@ impl Analyzer<'_, '_> { } } - if let Some(super_class) = self.scope.get_super_class(true) { + if let Some(super_class) = self.scope.borrow().get_super_class(true) { if let Ok(v) = self.access_property(*span, &super_class, prop, type_mode, IdCtx::Var, opts) { return Ok(v); } @@ -1795,10 +1799,11 @@ impl Analyzer<'_, '_> { } if let Type::This(..) = obj.normalize() { + let b = self.scope.borrow(); let scope = if self.ctx.in_computed_prop_name { - self.scope.scope_of_computed_props() + b.scope_of_computed_props() } else { - Some(&self.scope) + Some(&*b) }; if let Some(this) = scope.and_then(|scope| scope.this().map(Cow::into_owned)) { if this.normalize_instance().is_this() { @@ -2048,7 +2053,7 @@ impl Analyzer<'_, '_> { return Ok(Type::any(span, Default::default())); } - if let Some(declaring) = self.scope.declaring_prop.as_ref() { + if let Some(declaring) = self.scope.borrow().declaring_prop.as_ref() { if class_prop.key == *declaring.sym() { return Err(ErrorKind::ReferencedInInit { span }.into()); } @@ -2347,8 +2352,8 @@ impl Analyzer<'_, '_> { Type::Array(Array { elem_type, .. }) => { let elem_type = elem_type.clone().freezed(); - if self.scope.should_store_type_params() { - self.scope.store_type_param(Id::word("T".into()), *elem_type.clone()); + if self.scope.borrow().should_store_type_params() { + self.scope.borrow().store_type_param(Id::word("T".into()), *elem_type.clone()); } if let Key::Computed(prop) = prop { @@ -3021,7 +3026,7 @@ impl Analyzer<'_, '_> { Type::This(..) => { // TODO(kdy1): Use parent scope in computed property names. - if let Some(this) = self.scope.this().map(|this| this.into_owned()) { + if let Some(this) = self.scope.borrow().this().map(|this| this.into_owned()) { if self.ctx.in_computed_prop_name { if !self.ctx.in_class_member { self.storage @@ -3041,11 +3046,11 @@ impl Analyzer<'_, '_> { return Ok(Type::any(span, Default::default())); } + let b = self.scope.borrow(); let scope = if self.ctx.in_computed_prop_name { - self.scope.scope_of_computed_props() + b.scope_of_computed_props() } else { - self.scope - .first(|scope| !matches!(scope.kind(), ScopeKind::TypeParams | ScopeKind::Flow)) + b.first(|scope| !matches!(scope.kind(), ScopeKind::TypeParams | ScopeKind::Flow)) }; match scope.map(|scope| scope.kind()) { @@ -3218,7 +3223,7 @@ impl Analyzer<'_, '_> { match &r.type_name { RTsEntityName::TsQualifiedName(_) => {} RTsEntityName::Ident(i) => { - if let Some(class) = self.scope.get_this_class_name() { + if let Some(class) = self.scope.borrow().get_this_class_name() { if class == *i { return self.access_property( span, @@ -3366,8 +3371,8 @@ impl Analyzer<'_, '_> { } /// TODO(kdy1): Clarify this. - fn type_to_query_if_required(&mut self, span: Span, i: &RIdent, ty: Type) -> Type { - if self.scope.is_in_call() { + fn type_to_query_if_required(&self, span: Span, i: &RIdent, ty: Type) -> Type { + if self.scope.borrow().is_in_call() { return ty; } @@ -3392,7 +3397,7 @@ impl Analyzer<'_, '_> { } /// Expand type parameters using `type_args`. - pub(crate) fn expand_generics_with_type_args(&mut self, span: Span, ty: Type, type_args: &TypeParamInstantiation) -> VResult { + pub(crate) fn expand_generics_with_type_args(&self, span: Span, ty: Type, type_args: &TypeParamInstantiation) -> VResult { let _tracing = dev_span!("expand_generics_with_type_args"); match ty.normalize() { @@ -3498,7 +3503,7 @@ impl Analyzer<'_, '_> { } /// Returned type reflects conditional type facts. - pub(super) fn type_of_var(&mut self, i: &RIdent, type_mode: TypeOfMode, type_args: Option<&TypeParamInstantiation>) -> VResult { + pub(super) fn type_of_var(&self, i: &RIdent, type_mode: TypeOfMode, type_args: Option<&TypeParamInstantiation>) -> VResult { let _tracing = dev_span!("type_of_var"); let span = i.span(); @@ -3514,7 +3519,7 @@ impl Analyzer<'_, '_> { let id: Id = i.into(); let name: Name = i.into(); - if self.scope.is_declaring_fn(&id) { + if self.scope.borrow().is_declaring_fn(&id) { // We will expand this type query to proper type while calculating returns types // of a function. return Ok(Type::Query(QueryType { @@ -3644,12 +3649,12 @@ impl Analyzer<'_, '_> { /// Returned type does not reflects conditional type facts. (like Truthy / /// exclusion) - fn type_of_raw_var(&mut self, i: &RIdent, type_mode: TypeOfMode) -> VResult { - info!("({}) type_of_raw_var({})", self.scope.depth(), Id::from(i)); + fn type_of_raw_var(&self, i: &RIdent, type_mode: TypeOfMode) -> VResult { + info!("({}) type_of_raw_var({})", self.scope.borrow().depth(), Id::from(i)); // See documentation on Analyzer.cur_module_name to understand what we are doing // here. - if let Some(cur_module) = self.scope.current_module_name() { + if let Some(cur_module) = self.scope.borrow().current_module_name() { let ty = self.find_type(&cur_module)?; if let Some(ty) = ty { for ty in ty { @@ -3665,7 +3670,7 @@ impl Analyzer<'_, '_> { let span = i.span().with_ctxt(SyntaxContext::empty()); - if let Some(ref cls_name) = self.scope.this_class_name { + if let Some(ref cls_name) = self.scope.borrow().this_class_name { if *cls_name == i { warn!("Creating ref because we are currently defining a class: {}", i.sym); return Ok(Type::StaticThis(StaticThis { @@ -3681,7 +3686,7 @@ impl Analyzer<'_, '_> { if let js_word!("arguments") = i.sym { // `arguments` cannot be used as implicit variable if target <= ES5 let arguments_point_to_arrow = Some(true) - == self.scope.matches(|scope| { + == self.scope.borrow().matches(|scope| { if scope.is_root() { return Some(false); } @@ -3695,7 +3700,7 @@ impl Analyzer<'_, '_> { let arguments_points_async_fn = Some(true) == { let ctx = self.ctx; - self.scope.matches(|scope| { + self.scope.borrow().matches(|scope| { if scope.is_root() { return Some(false); } @@ -3708,9 +3713,9 @@ impl Analyzer<'_, '_> { }) }; - let is_argument_defined_in_current_scope = self.scope.vars.contains_key(&i.clone().into()); + let is_argument_defined_in_current_scope = self.scope.borrow().vars.contains_key(&i.clone().into()); - if !self.scope.is_arguments_implicitly_defined() { + if !self.scope.borrow().is_arguments_implicitly_defined() { self.storage.report(ErrorKind::InvalidUseOfArgumentsInEs3OrEs5 { span }.into()) } else if arguments_point_to_arrow && !is_argument_defined_in_current_scope { self.storage.report(ErrorKind::InvalidUseOfArgumentsInEs3OrEs5 { span }.into()); @@ -3752,11 +3757,11 @@ impl Analyzer<'_, '_> { } if let Some(ty) = self.find_imported_var(&i.into())? { - debug!("({}) type_of({}): resolved import", self.scope.depth(), Id::from(i)); + debug!("({}) type_of({}): resolved import", self.scope.borrow().depth(), Id::from(i)); return Ok(ty); } - if let Some(v) = self.scope.vars.get(&i.into()) { + if let Some(v) = self.scope.borrow().vars.get(&i.into()) { if let VarKind::Fn = v.kind { if let TypeOfMode::LValue = type_mode { return Err(ErrorKind::CannotAssignToFunction { span }.into()); @@ -3791,7 +3796,7 @@ impl Analyzer<'_, '_> { let ty_str = dump_type_as_string(&ty); debug!("find_var_type returned a type: {}", ty_str); let mut ty = ty.into_owned(); - if self.scope.kind().allows_respanning() { + if self.scope.borrow().kind().allows_respanning() { if self.is_implicitly_typed(&ty) { ty.metadata_mut().implicit = true; } @@ -3823,8 +3828,8 @@ impl Analyzer<'_, '_> { } // Check `declaring` before checking variables. - if self.scope.is_declaring(&i.into()) { - debug!("({}) reference in initialization: {}", self.scope.depth(), i.sym); + if self.scope.borrow().is_declaring(&i.into()) { + debug!("({}) reference in initialization: {}", self.scope.borrow().depth(), i.sym); // Report an error if a variable is used before initialization. (|| { @@ -3836,7 +3841,7 @@ impl Analyzer<'_, '_> { // If a method or a function scope exists before the scope declaring the // variable, it means current statement will be evaluated after the variable is // initialized. - if let Some(scope) = self.scope.first(|scope| { + if let Some(scope) = self.scope.borrow().first(|scope| { if scope.declaring.contains(&i.into()) { return true; } @@ -3857,7 +3862,7 @@ impl Analyzer<'_, '_> { self.storage.report(ErrorKind::BlockScopedVarUsedBeforeInit { span }.into()) })(); - if self.scope.can_access_declaring_regardless_of_context(&i.into()) { + if self.scope.borrow().can_access_declaring_regardless_of_context(&i.into()) { return Ok(Type::any(span, Default::default())); } @@ -3877,7 +3882,7 @@ impl Analyzer<'_, '_> { if self.env.target() <= EsVersion::Es5 { // `arguments` cannot be used as implicit variable if target <= ES5 let arguments_point_to_arrow = Some(true) - == self.scope.matches(|scope| { + == self.scope.borrow().matches(|scope| { if scope.is_root() { return Some(false); } @@ -3889,11 +3894,11 @@ impl Analyzer<'_, '_> { } }); - if !self.scope.is_arguments_implicitly_defined() || arguments_point_to_arrow { + if !self.scope.borrow().is_arguments_implicitly_defined() || arguments_point_to_arrow { self.storage.report(ErrorKind::InvalidUseOfArgumentsInEs3OrEs5 { span }.into()) } } else { - if !self.scope.is_arguments_implicitly_defined() { + if !self.scope.borrow().is_arguments_implicitly_defined() { self.storage.report(ErrorKind::NoSuchVar { span, name: i.into() }.into()) } } @@ -3933,10 +3938,11 @@ impl Analyzer<'_, '_> { } else { if let Some(scope) = self .scope + .borrow() .first_kind(|kind| matches!(kind, ScopeKind::Class | ScopeKind::ObjectLit)) { if let ScopeKind::ObjectLit = scope.kind() { - if let Some(declaring_prop) = self.scope.declaring_prop() { + if let Some(declaring_prop) = self.scope.borrow().declaring_prop() { if *declaring_prop.sym() == i.sym { return Err(ErrorKind::NoSuchVar { span, @@ -4019,13 +4025,13 @@ impl Analyzer<'_, '_> { } } - pub(crate) fn type_of_ts_entity_name(&mut self, span: Span, n: &RExpr, type_args: Option<&TypeParamInstantiation>) -> VResult { + pub(crate) fn type_of_ts_entity_name(&self, span: Span, n: &RExpr, type_args: Option<&TypeParamInstantiation>) -> VResult { let _tracing = dev_span!("type_of_ts_entity_name"); self.type_of_ts_entity_name_inner(span, n, type_args) } - fn type_of_ts_entity_name_inner(&mut self, span: Span, n: &RExpr, type_args: Option<&TypeParamInstantiation>) -> VResult { + fn type_of_ts_entity_name_inner(&self, span: Span, n: &RExpr, type_args: Option<&TypeParamInstantiation>) -> VResult { let _tracing = dev_span!("type_of_ts_entity_name_inner"); let span = span.with_ctxt(SyntaxContext::empty()); @@ -4205,7 +4211,7 @@ impl Analyzer<'_, '_> { if let TypeOfMode::RValue = type_mode { if let Some(name) = &name { - if let Some(mut ty) = self.scope.get_type_from_name(name) { + if let Some(mut ty) = self.scope.borrow().get_type_from_name(name) { ty.respan(span); return Ok(ty); } @@ -4371,14 +4377,14 @@ impl Analyzer<'_, '_> { let RSuper { span, .. } = *obj; let mut obj_ty = { - if self.scope.cannot_use_this_because_super_not_called() { + if self.scope.borrow().cannot_use_this_because_super_not_called() { self.storage.report(ErrorKind::SuperUsedBeforeCallingSuper { span }.into()) } self.report_error_for_super_reference_in_compute_keys(span, false); if self.ctx.super_references_super_class { - if let Some(v) = self.scope.get_super_class(self.ctx.is_static()) { + if let Some(v) = self.scope.borrow().get_super_class(self.ctx.is_static()) { v } else { self.storage.report(ErrorKind::SuperInClassWithoutSuper { span }.into()); @@ -4492,6 +4498,7 @@ impl Analyzer<'_, '_> { match self .scope + .borrow() .first_kind(|kind| match kind { ScopeKind::TypeParams | ScopeKind::Flow diff --git a/crates/stc_ts_file_analyzer/src/analyzer/expr/object.rs b/crates/stc_ts_file_analyzer/src/analyzer/expr/object.rs index 22e84097bc..8b45df47d9 100644 --- a/crates/stc_ts_file_analyzer/src/analyzer/expr/object.rs +++ b/crates/stc_ts_file_analyzer/src/analyzer/expr/object.rs @@ -57,7 +57,7 @@ impl Analyzer<'_, '_> { /// /// Type of `a` in the code above is `{ a: number, b?: undefined } | { /// a:number, b: string }`. - pub(super) fn normalize_union(&mut self, ty: &mut Type, preserve_specified: bool) { + pub(super) fn normalize_union(&self, ty: &mut Type, preserve_specified: bool) { let _tracing = dev_span!("normalize_union"); let start = Instant::now(); diff --git a/crates/stc_ts_file_analyzer/src/analyzer/function/mod.rs b/crates/stc_ts_file_analyzer/src/analyzer/function/mod.rs index 7f215f3a10..f3a739340a 100644 --- a/crates/stc_ts_file_analyzer/src/analyzer/function/mod.rs +++ b/crates/stc_ts_file_analyzer/src/analyzer/function/mod.rs @@ -95,9 +95,9 @@ impl Analyzer<'_, '_> { } let params = { - let prev_len = child.scope.declaring_parameters.len(); + let prev_len = child.scope.borrow().declaring_parameters.len(); let ids: Vec = find_ids_in_pat(&f.params); - child.scope.declaring_parameters.extend(ids); + child.scope.borrow_mut().declaring_parameters.extend(ids); let ctx = Ctx { pat_mode: PatMode::Decl, @@ -108,7 +108,7 @@ impl Analyzer<'_, '_> { }; let res = f.params.validate_with(&mut *child.with_ctx(ctx)); - child.scope.declaring_parameters.truncate(prev_len); + child.scope.borrow_mut().declaring_parameters.truncate(prev_len); res? }; @@ -122,7 +122,7 @@ impl Analyzer<'_, '_> { } .freezed(); - child.scope.declared_return_type = declared_ret_ty.clone(); + child.scope.borrow().declared_return_type = declared_ret_ty.clone(); if let Some(ty) = &mut declared_ret_ty { ty.freeze(); @@ -267,7 +267,7 @@ impl Analyzer<'_, '_> { } impl Analyzer<'_, '_> { - pub(crate) fn fn_to_type_element(&mut self, f: &Function) -> VResult { + pub(crate) fn fn_to_type_element(&self, f: &Function) -> VResult { Ok(TypeElement::Call(CallSignature { span: f.span.with_ctxt(SyntaxContext::empty()), params: f.params.clone(), @@ -357,8 +357,8 @@ impl Analyzer<'_, '_> { // } if let Some(name) = name { - assert_eq!(self.scope.declaring_fn, None); - self.scope.declaring_fn = Some(name.into()); + assert_eq!(self.scope.borrow().declaring_fn, None); + self.scope.borrow().declaring_fn = Some(name.into()); } let mut fn_ty: ty::Function = f.validate_with_args(self, name)?; @@ -402,7 +402,7 @@ impl Analyzer<'_, '_> { }; if let Some(name) = name { - self.scope.declaring_fn = None; + self.scope.borrow().declaring_fn = None; } fn_ty diff --git a/crates/stc_ts_file_analyzer/src/analyzer/function/return_type.rs b/crates/stc_ts_file_analyzer/src/analyzer/function/return_type.rs index dabe0e70d9..76473178fd 100644 --- a/crates/stc_ts_file_analyzer/src/analyzer/function/return_type.rs +++ b/crates/stc_ts_file_analyzer/src/analyzer/function/return_type.rs @@ -43,7 +43,7 @@ impl VisitMut for FnReturnTypeHandler<'_, '_, '_> { copied: false, ty: Some(ty), .. - }) = self.analyzer.scope.vars.get(&var_name.clone().into()) + }) = self.analyzer.scope.borrow().vars.get(&var_name.clone().into()) { *ret_ty = ty.clone(); } diff --git a/crates/stc_ts_file_analyzer/src/analyzer/generic/expander.rs b/crates/stc_ts_file_analyzer/src/analyzer/generic/expander.rs index 1ed5bc8ba2..4740855607 100644 --- a/crates/stc_ts_file_analyzer/src/analyzer/generic/expander.rs +++ b/crates/stc_ts_file_analyzer/src/analyzer/generic/expander.rs @@ -45,7 +45,7 @@ pub(crate) struct ExtendsOpts { /// Generic expander. impl Analyzer<'_, '_> { pub(in super::super) fn instantiate_type_params_using_args( - &mut self, + &self, span: Span, type_params: &TypeParamDecl, type_args: &TypeParamInstantiation, @@ -92,7 +92,7 @@ impl Analyzer<'_, '_> { ///z T extends { /// x: infer P extends number ? infer P : string; /// } ? P : never - pub(in super::super) fn expand_type_params(&mut self, params: &FxHashMap, ty: T, opts: ExpandGenericOpts) -> VResult + pub(in super::super) fn expand_type_params(&self, params: &FxHashMap, ty: T, opts: ExpandGenericOpts) -> VResult where T: for<'aa> FoldWith> + Fix, { @@ -119,7 +119,7 @@ impl Analyzer<'_, '_> { } /// Returns `Some(true)` if `child` extends `parent`. - pub(crate) fn extends(&mut self, span: Span, child: &Type, parent: &Type, opts: ExtendsOpts) -> Option { + pub(crate) fn extends(&self, span: Span, child: &Type, parent: &Type, opts: ExtendsOpts) -> Option { let _tracing = if cfg!(debug_assertions) { let child = dump_type_as_string(child); let parent = dump_type_as_string(parent); diff --git a/crates/stc_ts_file_analyzer/src/analyzer/generic/inference.rs b/crates/stc_ts_file_analyzer/src/analyzer/generic/inference.rs index 3aca4dcd45..89b5393296 100644 --- a/crates/stc_ts_file_analyzer/src/analyzer/generic/inference.rs +++ b/crates/stc_ts_file_analyzer/src/analyzer/generic/inference.rs @@ -162,12 +162,12 @@ impl Default for InferencePriority { impl Analyzer<'_, '_> { /// Ported from `inferFromMatchingTypes` of `tsc`. pub(super) fn infer_from_matching_types( - &mut self, + &self, span: Span, inferred: &mut InferData, sources: &[Type], targets: &[Type], - matches: impl Fn(&mut Analyzer, &Type, &Type) -> bool, + matches: impl Fn(&Analyzer, &Type, &Type) -> bool, opts: InferTypeOpts, ) -> VResult<(Vec, Vec)> { let _tracing = dev_span!("infer_from_matching_types"); @@ -215,7 +215,7 @@ impl Analyzer<'_, '_> { /// Ported from `tsc`. pub(super) fn infer_type_using_union( - &mut self, + &self, span: Span, inferred: &mut InferData, param: &Union, @@ -283,7 +283,7 @@ impl Analyzer<'_, '_> { /// Ported from `inferToMultipleTypes` of `tsc`. pub(super) fn infer_to_multiple_types( - &mut self, + &self, span: Span, inferred: &mut InferData, source: &Type, @@ -399,7 +399,7 @@ impl Analyzer<'_, '_> { /// Ported from `inferFromTypes` of `tsc`. pub(super) fn infer_from_types( - &mut self, + &self, span: Span, inferred: &mut InferData, source: &Type, @@ -410,7 +410,7 @@ impl Analyzer<'_, '_> { } pub(super) fn infer_with_priority( - &mut self, + &self, span: Span, inferred: &mut InferData, source: &Type, @@ -427,7 +427,7 @@ impl Analyzer<'_, '_> { /// `inferToMultipleTypesWithPriority` pub(super) fn infer_to_multiple_types_with_priority( - &mut self, + &self, span: Span, inferred: &mut InferData, source: &Type, @@ -447,7 +447,7 @@ impl Analyzer<'_, '_> { /// Ported from `inferFromContravariantTypes` of `tsc`. pub(super) fn infer_from_contravariant_types( - &mut self, + &self, span: Span, inferred: &mut InferData, source: &Type, @@ -463,7 +463,7 @@ impl Analyzer<'_, '_> { } /// Ported from `getInferenceInfoForType` of `tsc`. - fn get_inference_info_for_type<'a>(&mut self, inferred: &'a mut InferData, ty: &Type) -> Option<&'a mut InferenceInfo> { + fn get_inference_info_for_type<'a>(&self, inferred: &'a mut InferData, ty: &Type) -> Option<&'a mut InferenceInfo> { if let Type::Param(param) = ty { return inferred.type_params.get_mut(¶m.name); } @@ -472,7 +472,7 @@ impl Analyzer<'_, '_> { } /// Ported from `getSingleTypeVariableFromIntersectionTypes` of `tsc`. - fn get_single_type_variable_from_intersection_types(&mut self, span: Span, inferred: &mut InferData, types: &[Type]) -> Option { + fn get_single_type_variable_from_intersection_types(&self, span: Span, inferred: &mut InferData, types: &[Type]) -> Option { let mut type_var: Option = None; for ty in types { @@ -497,7 +497,7 @@ impl Analyzer<'_, '_> { /// Ported from `inferToTemplateLiteralType` of `tsc`. pub(super) fn infer_to_tpl_lit_type( - &mut self, + &self, span: Span, inferred: &mut InferData, source: &Type, @@ -777,7 +777,7 @@ impl Analyzer<'_, '_> { } /// Ported from `inferTypesFromTemplateLiteralType` of `tsc`. - pub(crate) fn infer_types_from_tpl_lit_type(&mut self, span: Span, source: &Type, target: &TplType) -> VResult>> { + pub(crate) fn infer_types_from_tpl_lit_type(&self, span: Span, source: &Type, target: &TplType) -> VResult>> { match source.normalize() { Type::Lit(LitType { lit: RTsLit::Str(source), .. @@ -837,7 +837,7 @@ impl Analyzer<'_, '_> { #[allow(unused_assignments)] #[allow(clippy::needless_range_loop)] fn infer_from_lit_parts_to_tpl_lit( - &mut self, + &self, span: Span, source_texts: &[Atom], source_types: &[Type], @@ -944,7 +944,7 @@ impl Analyzer<'_, '_> { } pub(super) fn insert_inferred( - &mut self, + &self, span: Span, inferred: &mut InferData, tp: &TypeParam, @@ -978,7 +978,7 @@ impl Analyzer<'_, '_> { /// let e5 = f(data, data2); // Error /// ``` pub(super) fn insert_inferred_raw( - &mut self, + &self, span: Span, inferred: &mut InferData, name: Id, @@ -1024,14 +1024,7 @@ impl Analyzer<'_, '_> { self.upsert_inferred(span, inferred, name, &ty, opts) } - pub(super) fn upsert_inferred( - &mut self, - span: Span, - inferred: &mut InferData, - name: Id, - arg: &Type, - opts: InferTypeOpts, - ) -> VResult<()> { + pub(super) fn upsert_inferred(&self, span: Span, inferred: &mut InferData, name: Id, arg: &Type, opts: InferTypeOpts) -> VResult<()> { let arg = match arg.normalize() { Type::Union(arg) if opts.exclude_null_and_undefined => { Cow::Owned(Type::new_union(arg.span, arg.types.iter().filter(|ty| !ty.is_null_or_undefined()).cloned()).freezed()) @@ -1224,7 +1217,7 @@ impl Analyzer<'_, '_> { /// Infer types, using `param` and `arg`. pub(crate) fn infer_type_with_types( - &mut self, + &self, span: Span, type_params: &[TypeParam], param: &Type, @@ -1253,7 +1246,7 @@ impl Analyzer<'_, '_> { /// Handle some special builtin types pub(super) fn infer_builtin( - &mut self, + &self, span: Span, inferred: &mut InferData, param: &Type, @@ -1324,7 +1317,7 @@ impl Analyzer<'_, '_> { } pub(super) fn infer_type_using_interface( - &mut self, + &self, span: Span, inferred: &mut InferData, param: &Interface, @@ -1359,7 +1352,7 @@ impl Analyzer<'_, '_> { } fn infer_type_using_interface_and_interface( - &mut self, + &self, span: Span, inferred: &mut InferData, param: &Interface, @@ -1373,7 +1366,7 @@ impl Analyzer<'_, '_> { /// Compare fields. pub(super) fn infer_type_using_type_lit_and_type_lit( - &mut self, + &self, span: Span, inferred: &mut InferData, param: &TypeLit, @@ -1385,7 +1378,7 @@ impl Analyzer<'_, '_> { /// Returns `Ok(true)` if this method know how to infer types. pub(super) fn infer_type_by_converting_to_type_lit( - &mut self, + &self, span: Span, inferred: &mut InferData, param: &Type, @@ -1413,7 +1406,7 @@ impl Analyzer<'_, '_> { } fn infer_type_using_type_elements_and_type_elements( - &mut self, + &self, span: Span, inferred: &mut InferData, param: &[TypeElement], @@ -1606,7 +1599,7 @@ impl Analyzer<'_, '_> { } pub(super) fn infer_type_using_readonly( - &mut self, + &self, span: Span, inferred: &mut InferData, param: &Readonly, @@ -1617,7 +1610,7 @@ impl Analyzer<'_, '_> { } pub(super) fn infer_types_using_class( - &mut self, + &self, span: Span, inferred: &mut InferData, param: &Class, @@ -1628,7 +1621,7 @@ impl Analyzer<'_, '_> { } pub(super) fn infer_types_using_class_def( - &mut self, + &self, span: Span, inferred: &mut InferData, param: &ClassDef, @@ -1757,7 +1750,7 @@ impl Analyzer<'_, '_> { /// Prevent generalizations if a type parameter extends literal. pub(super) fn prevent_generalization_of_inferred_types( - &mut self, + &self, type_params: &[TypeParam], inferred: &mut InferData, is_from_type_ann: bool, diff --git a/crates/stc_ts_file_analyzer/src/analyzer/generic/mod.rs b/crates/stc_ts_file_analyzer/src/analyzer/generic/mod.rs index c2191f369e..87422b992f 100644 --- a/crates/stc_ts_file_analyzer/src/analyzer/generic/mod.rs +++ b/crates/stc_ts_file_analyzer/src/analyzer/generic/mod.rs @@ -95,7 +95,7 @@ impl Analyzer<'_, '_> { /// This method accepts Option<&[TypeParamInstantiation]> because user may /// provide only some of type arguments. pub(super) fn infer_arg_types( - &mut self, + &self, span: Span, base: Option<&TypeParamInstantiation>, type_params: &[TypeParam], @@ -361,7 +361,7 @@ impl Analyzer<'_, '_> { /// Handles `infer U`. pub(super) fn infer_ts_infer_types( - &mut self, + &self, span: Span, base: &Type, concrete: &Type, @@ -487,7 +487,7 @@ impl Analyzer<'_, '_> { /// arr([1, u]) // Ok /// arr([{}, u]) // Ok /// ``` - fn infer_type(&mut self, span: Span, inferred: &mut InferData, param: &Type, arg: &Type, opts: InferTypeOpts) -> VResult<()> { + fn infer_type(&self, span: Span, inferred: &mut InferData, param: &Type, arg: &Type, opts: InferTypeOpts) -> VResult<()> { if self.config.is_builtin { return Ok(()); } @@ -520,7 +520,7 @@ impl Analyzer<'_, '_> { /// /// /// TODO(kdy1): Optimize - fn infer_type_inner(&mut self, span: Span, inferred: &mut InferData, param: &Type, arg: &Type, mut opts: InferTypeOpts) -> VResult<()> { + fn infer_type_inner(&self, span: Span, inferred: &mut InferData, param: &Type, arg: &Type, mut opts: InferTypeOpts) -> VResult<()> { if self.config.is_builtin { return Ok(()); } @@ -812,7 +812,12 @@ impl Analyzer<'_, '_> { return Ok(()); } - debug!("({}): Inferred `{}` as {}", self.scope.depth(), name, dump_type_as_string(arg)); + debug!( + "({}): Inferred `{}` as {}", + self.scope.borrow().depth(), + name, + dump_type_as_string(arg) + ); self.upsert_inferred(span, inferred, name.clone(), arg, opts)?; @@ -1473,7 +1478,7 @@ impl Analyzer<'_, '_> { } fn infer_type_using_mapped_type( - &mut self, + &self, span: Span, inferred: &mut InferData, param: &Mapped, @@ -2209,7 +2214,7 @@ impl Analyzer<'_, '_> { } fn infer_type_using_tuple_and_tuple( - &mut self, + &self, span: Span, inferred: &mut InferData, param: &Tuple, @@ -2289,7 +2294,7 @@ impl Analyzer<'_, '_> { } fn infer_type_of_fn_param( - &mut self, + &self, span: Span, inferred: &mut InferData, param: &FnParam, @@ -2310,7 +2315,7 @@ impl Analyzer<'_, '_> { } fn infer_type_of_fn_params( - &mut self, + &self, span: Span, inferred: &mut InferData, params: &[FnParam], @@ -2336,7 +2341,7 @@ impl Analyzer<'_, '_> { Ok(()) } - fn rename_inferred(&mut self, span: Span, inferred: &mut InferData, arg_type_params: &TypeParamDecl) -> VResult<()> { + fn rename_inferred(&self, span: Span, inferred: &mut InferData, arg_type_params: &TypeParamDecl) -> VResult<()> { info!("rename_inferred"); if arg_type_params.params.iter().any(|v| inferred.errored.contains(&v.name)) { @@ -2396,7 +2401,7 @@ fn array_elem_type(t: &Type) -> Option<&Type> { /// Handles renaming of the type parameters. impl Analyzer<'_, '_> { - pub(super) fn rename_type_params(&mut self, span: Span, mut ty: Type, type_ann: Option<&Type>) -> VResult { + pub(super) fn rename_type_params(&self, span: Span, mut ty: Type, type_ann: Option<&Type>) -> VResult { if self.config.is_builtin { return Ok(ty); } diff --git a/crates/stc_ts_file_analyzer/src/analyzer/hoisting/mod.rs b/crates/stc_ts_file_analyzer/src/analyzer/hoisting/mod.rs index 4e472fcd08..f2683f6361 100644 --- a/crates/stc_ts_file_analyzer/src/analyzer/hoisting/mod.rs +++ b/crates/stc_ts_file_analyzer/src/analyzer/hoisting/mod.rs @@ -22,7 +22,7 @@ impl Analyzer<'_, '_> { dedup(&mut order); - if self.scope.is_root() { + if self.scope.borrow().is_root() { // We should track type declarations. for &idx in &order { let type_decl_id = type_decl_id(stmts[idx]); @@ -33,7 +33,7 @@ impl Analyzer<'_, '_> { } for idx in order { - if self.scope.is_root() { + if self.scope.borrow().is_root() { let module_id = self.storage.module_id(idx); self.ctx.module_id = module_id; } @@ -45,7 +45,7 @@ impl Analyzer<'_, '_> { let node_id = stmts[idx].node_id(); stmts[idx].visit_with(self); - if self.scope.is_root() { + if self.scope.borrow().is_root() { let prepended = self.data.prepend_stmts.drain(..); let appended = self.data.append_stmts.drain(..); diff --git a/crates/stc_ts_file_analyzer/src/analyzer/mod.rs b/crates/stc_ts_file_analyzer/src/analyzer/mod.rs index 5b68769d38..6717f27329 100644 --- a/crates/stc_ts_file_analyzer/src/analyzer/mod.rs +++ b/crates/stc_ts_file_analyzer/src/analyzer/mod.rs @@ -1,5 +1,5 @@ use std::{ - cell::Cell, + cell::{Cell, RefCell}, fmt::Debug, mem::take, ops::{Deref, DerefMut}, @@ -236,7 +236,7 @@ pub struct Analyzer<'scope, 'b> { export_equals_span: Span, - scope: Scope<'scope>, + scope: RefCell>, ctx: Ctx, @@ -406,7 +406,7 @@ impl<'scope, 'b> Analyzer<'scope, 'b> { env: Env, cm: Arc, comments: StcComments, - mut storage: Storage<'b>, + storage: Storage<'b>, loader: &'b dyn Load, debugger: Option, ) -> Self { @@ -480,7 +480,7 @@ impl<'scope, 'b> Analyzer<'scope, 'b> { storage, mutations, export_equals_span: DUMMY_SP, - scope, + scope: RefCell::new(scope), config: InnerConfig { is_builtin, is_dts }, ctx: Ctx { module_id: ModuleId::builtin(), @@ -599,7 +599,8 @@ impl<'scope, 'b> Analyzer<'scope, 'b> { }; let data = take(&mut self.data); - let child_scope = Scope::new(&self.scope, kind, facts); + let scope = self.scope.borrow(); + let child_scope = Scope::new(&scope, kind, facts); let (ret, errors, cur_facts, mut child_scope, mutations, data) = { let mut child = self.new(child_scope, data); child.mutations = mutations; @@ -618,7 +619,7 @@ impl<'scope, 'b> Analyzer<'scope, 'b> { ret, errors, child.cur_facts, - child.scope.remove_parent(), + child.scope.borrow_mut().remove_parent(), child.mutations.take(), take(&mut child.data), ) @@ -631,8 +632,8 @@ impl<'scope, 'b> Analyzer<'scope, 'b> { hook(self); - self.scope.move_types_from_child(&mut child_scope); - self.scope.move_vars_from_child(&mut child_scope); + self.scope.borrow_mut().move_types_from_child(&mut child_scope); + self.scope.borrow_mut().move_vars_from_child(&mut child_scope); if kind == ScopeKind::Module { self.data.for_module = module_data; } @@ -642,7 +643,7 @@ impl<'scope, 'b> Analyzer<'scope, 'b> { // These kinds of scope eats return statements ScopeKind::Module | ScopeKind::Method { .. } | ScopeKind::ArrowFn | ScopeKind::Fn => {} _ => { - self.scope.return_values += child_scope.return_values; + self.scope.borrow_mut().return_values += child_scope.return_values; } } @@ -1017,7 +1018,7 @@ impl Analyzer<'_, '_> { let mut ty = self .with_ctx(ctx) .with_child(ScopeKind::Module, Default::default(), |child: &mut Analyzer| { - child.scope.cur_module_name = match &decl.id { + child.scope.borrow_mut().cur_module_name = match &decl.id { RTsModuleName::Ident(i) => Some(i.into()), RTsModuleName::Str(_) => None, }; diff --git a/crates/stc_ts_file_analyzer/src/analyzer/pat.rs b/crates/stc_ts_file_analyzer/src/analyzer/pat.rs index eeddc018ca..8f7d46787c 100644 --- a/crates/stc_ts_file_analyzer/src/analyzer/pat.rs +++ b/crates/stc_ts_file_analyzer/src/analyzer/pat.rs @@ -246,7 +246,7 @@ impl Analyzer<'_, '_> { .transpose()? .freezed(); - let prev_declaring_len = self.scope.declaring.len(); + let prev_declaring_len = self.scope.borrow().declaring.len(); // Declaring names let mut names = vec![]; @@ -261,7 +261,7 @@ impl Analyzer<'_, '_> { return Err(ErrorKind::ThisNotAllowedInAccessor { span: p.span() }.into()); } if ty.is_some() { - self.scope.this = ty.clone(); + self.scope.borrow_mut().this = ty.clone(); } } @@ -269,7 +269,7 @@ impl Analyzer<'_, '_> { p.visit_with(&mut visitor); - self.scope.declaring.extend(names.clone()); + self.scope.borrow_mut().declaring.extend(names.clone()); if !self.config.is_builtin { ty = match self.add_vars( @@ -311,7 +311,7 @@ impl Analyzer<'_, '_> { PatMode::Decl => None, }; - self.scope.declaring.truncate(prev_declaring_len); + self.scope.borrow_mut().declaring.truncate(prev_declaring_len); // Mark pattern as optional if default value exists if let RPat::Assign(assign_pat) = p { @@ -431,7 +431,7 @@ impl Analyzer<'_, '_> { match p { RPat::Ident(i) if i.id.sym == *"this" => { - self.scope.this = Some(ty.clone()); + self.scope.borrow_mut().this = Some(ty.clone()); } _ => {} } diff --git a/crates/stc_ts_file_analyzer/src/analyzer/props.rs b/crates/stc_ts_file_analyzer/src/analyzer/props.rs index 148e77e819..a720655e64 100644 --- a/crates/stc_ts_file_analyzer/src/analyzer/props.rs +++ b/crates/stc_ts_file_analyzer/src/analyzer/props.rs @@ -190,9 +190,9 @@ impl Analyzer<'_, '_> { ..self.ctx }; - let old_this = self.scope.this.take(); + let old_this = self.scope.borrow_mut().this.take(); let res = self.with_ctx(ctx).validate_prop_inner(prop, object_type); - self.scope.this = old_this; + self.scope.borrow_mut().this = old_this; res } @@ -210,7 +210,8 @@ impl Analyzer<'_, '_> { debug_assert!(self.ctx.in_computed_prop_name); for used in used_type_params { - let scope = self.scope.first_kind(|kind| match kind { + let b = self.scope.borrow(); + let scope = b.first_kind(|kind| match kind { ScopeKind::Fn | ScopeKind::Method { .. } | ScopeKind::Module @@ -448,7 +449,7 @@ impl Analyzer<'_, '_> { // We mark as wip if !computed { if let RPropName::Ident(i) = &p.key { - child.scope.declaring_prop = Some(i.into()); + child.scope.borrow_mut().declaring_prop = Some(i.into()); }; } @@ -457,7 +458,7 @@ impl Analyzer<'_, '_> { let ret_ty = try_opt!(p.function.return_type.validate_with(child)); let ret_ty = ret_ty.map(|ty| ty.freezed()); - child.scope.declared_return_type = ret_ty.clone(); + child.scope.borrow_mut().declared_return_type = ret_ty.clone(); let mut inferred = None; diff --git a/crates/stc_ts_file_analyzer/src/analyzer/relation/mod.rs b/crates/stc_ts_file_analyzer/src/analyzer/relation/mod.rs index 9e4dd333f6..49e16abc9c 100644 --- a/crates/stc_ts_file_analyzer/src/analyzer/relation/mod.rs +++ b/crates/stc_ts_file_analyzer/src/analyzer/relation/mod.rs @@ -20,12 +20,12 @@ struct IsRelatedData {} impl Analyzer<'_, '_> { /// Ported from `isTypeRelatedTo` of `tsc`. - pub(crate) fn is_type_related_to(&mut self, source: &Type, target: &Type, relation: Relation) -> bool { + pub(crate) fn is_type_related_to(&self, source: &Type, target: &Type, relation: Relation) -> bool { let mut data = IsRelatedData::default(); self.is_type_related_to_inner(&mut data, source, target, relation) } - fn is_type_related_to_inner(&mut self, data: &mut IsRelatedData, source: &Type, target: &Type, relation: Relation) -> bool { + fn is_type_related_to_inner(&self, data: &mut IsRelatedData, source: &Type, target: &Type, relation: Relation) -> bool { if source.type_eq(target) { return true; } @@ -49,7 +49,7 @@ impl Analyzer<'_, '_> { /// /// Ported from `isSimpleTypeRelatedTo` of `tsc`. #[allow(clippy::nonminimal_bool)] - fn is_simple_type_related_to(&mut self, source: &Type, target: &Type, relation: Relation) -> bool { + fn is_simple_type_related_to(&self, source: &Type, target: &Type, relation: Relation) -> bool { let (s, t) = (source, target); if t.is_any() || t.is_unknown() || s.is_never() { @@ -161,7 +161,7 @@ impl Analyzer<'_, '_> { /// TODO: Implement /// /// Ported from `checkTypeRelatedTo` of `tsc`. - fn check_type_related_to(&mut self, source: &Type, target: &Type, relation: Relation) -> bool { + fn check_type_related_to(&self, source: &Type, target: &Type, relation: Relation) -> bool { false } } diff --git a/crates/stc_ts_file_analyzer/src/analyzer/scope/mod.rs b/crates/stc_ts_file_analyzer/src/analyzer/scope/mod.rs index cfeadbe21f..0e3118ebb2 100644 --- a/crates/stc_ts_file_analyzer/src/analyzer/scope/mod.rs +++ b/crates/stc_ts_file_analyzer/src/analyzer/scope/mod.rs @@ -706,7 +706,7 @@ impl Analyzer<'_, '_> { /// - `expand_union` should be true if you are going to use it in /// assignment, and false if you are going to use it in user-visible /// stuffs (e.g. type annotation for .d.ts file) - pub(super) fn expand(&mut self, span: Span, ty: Type, opts: ExpandOpts) -> VResult { + pub(super) fn expand(&self, span: Span, ty: Type, opts: ExpandOpts) -> VResult { let _tracing = dev_span!("expand"); if !self.config.is_builtin { @@ -737,16 +737,16 @@ impl Analyzer<'_, '_> { Ok(ty) } - pub(super) fn expand_type_params_using_scope(&mut self, ty: Type) -> VResult { - let type_params = take(&mut self.scope.type_params); + pub(super) fn expand_type_params_using_scope(&self, ty: Type) -> VResult { + let type_params = take(&mut self.scope.borrow_mut().type_params); let res = self.expand_type_params(&type_params, ty, Default::default()); - self.scope.type_params = type_params; + self.scope.borrow_mut().type_params = type_params; res } /// Expands the type if it's [Type::Ref]. - pub(crate) fn expand_top_ref<'a>(&mut self, span: Span, ty: Cow<'a, Type>, opts: ExpandOpts) -> VResult> { + pub(crate) fn expand_top_ref<'a>(&self, span: Span, ty: Cow<'a, Type>, opts: ExpandOpts) -> VResult> { ty.assert_valid(); if !ty.is_ref_type() { @@ -775,7 +775,7 @@ impl Analyzer<'_, '_> { } let v = self.data.unmergable_type_decls.entry(id.clone()).or_default(); - v.push((span, self.scope.depth())); + v.push((span, self.scope.borrow().depth())); if v.len() < 2 { return; @@ -784,10 +784,10 @@ impl Analyzer<'_, '_> { let v = v .iter() .filter(|(x_span, depth)| { - if *depth == self.scope.depth() { + if *depth == self.scope.borrow().depth() { if *depth == 0 { true - } else if let Some(x) = self.scope.types.get(&id) { + } else if let Some(x) = self.scope.borrow().types.get(&id) { x.span() != span } else { false @@ -815,7 +815,7 @@ impl Analyzer<'_, '_> { let _tracing = dev_span!("register_type"); if cfg!(debug_assertions) { - debug!("[({})/types] Registering: {:?}", self.scope.depth(), name); + debug!("[({})/types] Registering: {:?}", self.scope.borrow().depth(), name); } let should_check_for_mixed_default_exports = ty.is_module(); @@ -887,7 +887,7 @@ impl Analyzer<'_, '_> { .export_stored_type(ty.span(), self.ctx.module_id, name.clone(), name.clone()); } - self.scope.register_type(name, ty.clone(), false); + self.scope.borrow_mut().register_type(name, ty.clone(), false); ty } else { @@ -902,12 +902,12 @@ impl Analyzer<'_, '_> { // Override class definitions. if should_override { - if let Some(kind) = self.scope.get_var(&name).map(|v| v.kind) { + if let Some(kind) = self.scope.borrow().get_var(&name).map(|v| v.kind) { self.override_var(kind, name.clone(), ty.clone()).report(&mut self.storage); } } - if (self.scope.is_root() || self.scope.is_module()) && !ty.is_type_param() { + if (self.scope.borrow().is_root() || self.scope.borrow().is_module()) && !ty.is_type_param() { self.storage .store_private_type(self.ctx.module_id, name.clone(), ty.clone(), should_override); @@ -928,7 +928,7 @@ impl Analyzer<'_, '_> { } } - self.scope.register_type(name, ty.clone(), should_override); + self.scope.borrow_mut().register_type(name, ty.clone(), should_override); ty } @@ -946,7 +946,7 @@ impl Analyzer<'_, '_> { return Ok(Type::any(span.with_ctxt(SyntaxContext::empty()), Default::default())); } if i.sym == js_word!("this") { - if let Some(this) = self.scope.this().map(Cow::into_owned) { + if let Some(this) = self.scope.borrow().this().map(Cow::into_owned) { return Ok(this); } else { return Ok(Type::This(ThisType { @@ -1024,7 +1024,7 @@ impl Analyzer<'_, '_> { #[inline(never)] pub(super) fn find_var(&self, name: &Id) -> Option<&VarInfo> { if cfg!(debug_assertions) { - debug!("({}) Analyzer.find_var(`{}`)", self.scope.depth(), name); + debug!("({}) Analyzer.find_var(`{}`)", self.scope.borrow().depth(), name); } static ANY_VAR: Lazy = Lazy::new(|| VarInfo { @@ -1036,7 +1036,8 @@ impl Analyzer<'_, '_> { is_actual_type_modified_in_loop: false, }); - let mut scope = Some(&self.scope); + let b = self.scope.borrow(); + let mut scope = Some(&*b); while let Some(s) = scope { if let Some(var) = s.vars.get(name) { @@ -1067,7 +1068,8 @@ impl Analyzer<'_, '_> { } // println!("({}) find_var_type({})", self.scope.depth(), name); - let mut scope = Some(&self.scope); + let b = self.scope.borrow(); + let mut scope = Some(&*b); while let Some(s) = scope { if let Some(v) = s.facts.vars.get(&Name::from(name)) { v.assert_clone_cheap(); @@ -1104,7 +1106,11 @@ impl Analyzer<'_, '_> { if let Some(var) = self.find_var(name) { if cfg!(debug_assertions) { - debug!("({}) find_var_type({}): Handled from scope.find_var", self.scope.depth(), name); + debug!( + "({}) find_var_type({}): Handled from scope.find_var", + self.scope.borrow().depth(), + name + ); } let name = Name::from(name); @@ -1121,7 +1127,7 @@ impl Analyzer<'_, '_> { }; ty.assert_clone_cheap(); - if let Some(excludes) = self.scope.facts.excludes.get(&name) { + if let Some(excludes) = self.scope.borrow().facts.excludes.get(&name) { if let Some(ty::Union { ref mut types, .. }) = ty.as_union_type_mut() { for ty in types { let span = (*ty).span(); @@ -1212,7 +1218,7 @@ impl Analyzer<'_, '_> { }) }); - if let Some(class) = &self.scope.get_this_class_name() { + if let Some(class) = &self.scope.borrow().get_this_class_name() { if *class == *name { // TODO(kdy1): Maybe change this to special variant. return Some(ItemRef::Single(iter::once(&STATIC_THIS))); @@ -1220,7 +1226,7 @@ impl Analyzer<'_, '_> { } if cfg!(debug_assertions) { - debug!("({}) Scope.find_type(`{}`)", self.scope.depth(), name); + debug!("({}) Scope.find_type(`{}`)", self.scope.borrow().depth(), name); } let mut src = vec![]; @@ -1235,7 +1241,7 @@ impl Analyzer<'_, '_> { } } - if let Some(ty) = self.scope.find_type(name) { + if let Some(ty) = self.scope.borrow().find_type(name) { if self.ctx.in_module { // In module mode, we should not merge user-defined types with builtin. // As `src` contains builtin types, we remove them. @@ -1280,7 +1286,7 @@ impl Analyzer<'_, '_> { ty.assert_clone_cheap(); } - op(self.scope.vars.entry(name).or_insert_with(|| VarInfo { + op(self.scope.get_mut().vars.entry(name).or_insert_with(|| VarInfo { kind: VarKind::Error, initialized: true, ty: ty.clone(), @@ -1306,20 +1312,25 @@ impl Analyzer<'_, '_> { ty.assert_valid(); debug!( "[({})/vars/destructor]: Declaring {:?} as {}", - self.scope.depth(), + self.scope.borrow().depth(), key, dump_type_as_string(&ty) ); - self.scope.destructure_vars.insert(key, ty.freezed()); + self.scope.borrow_mut().destructure_vars.insert(key, ty.freezed()); Ok(true) } else { - debug!("[({})/vars/destructor]: Declaring {:?} without type", self.scope.depth(), key); + debug!( + "[({})/vars/destructor]: Declaring {:?} without type", + self.scope.borrow().depth(), + key + ); Ok(false) } } pub fn find_destructor(&self, key: DestructureId) -> Option> { - let mut scope = Some(&self.scope); + let b = self.scope.borrow(); + let mut scope = Some(&*b); while let Some(s) = scope { if let Some(v) = s.destructure_vars.get(&key) { v.assert_clone_cheap(); @@ -1355,9 +1366,14 @@ impl Analyzer<'_, '_> { if let Some(ty) = &ty { ty.assert_valid(); - debug!("[({})/vars]: Declaring {} as {}", self.scope.depth(), name, dump_type_as_string(ty)); + debug!( + "[({})/vars]: Declaring {} as {}", + self.scope.borrow().depth(), + name, + dump_type_as_string(ty) + ); } else { - debug!("[({})/vars]: Declaring {} without type", self.scope.depth(), name,); + debug!("[({})/vars]: Declaring {} without type", self.scope.borrow().depth(), name,); } if let Some(ty) = &actual_ty { @@ -1478,7 +1494,7 @@ impl Analyzer<'_, '_> { } } - if self.scope.is_root() || self.scope.is_module() { + if self.scope.borrow().is_root() || self.scope.borrow().is_module() { self.storage.store_private_var( self.ctx.module_id, name.clone(), @@ -1488,14 +1504,14 @@ impl Analyzer<'_, '_> { let mut skip_storing_type = false; - match self.scope.vars.entry(name.clone()) { + match self.scope.borrow_mut().vars.entry(name.clone()) { Entry::Occupied(e) => { //println!("\tdeclare_var: found entry"); let (k, mut v) = e.remove_entry(); macro_rules! restore { () => {{ - self.scope.vars.insert(k, v); + self.scope.borrow_mut().vars.insert(k, v); }}; } @@ -1629,7 +1645,7 @@ impl Analyzer<'_, '_> { } } - self.scope.vars.insert(k, v); + self.scope.borrow_mut().vars.insert(k, v); } Entry::Vacant(e) => { //println!("\tdeclare_var: no entry"); @@ -2046,7 +2062,7 @@ impl ScopeKind { struct Expander<'a, 'b, 'c> { span: Span, - analyzer: &'a mut Analyzer<'b, 'c>, + analyzer: &'a Analyzer<'b, 'c>, dejavu: FxHashSet, full: bool, expand_union: bool, @@ -2079,7 +2095,7 @@ impl Expander<'_, '_, '_> { match type_name { RTsEntityName::Ident(ref i) => { - if let Some(class) = &self.analyzer.scope.get_this_class_name() { + if let Some(class) = &self.analyzer.scope.borrow().get_this_class_name() { if *class == *i { return Ok(Some(Type::This(ThisType { span, @@ -2261,7 +2277,12 @@ impl Expander<'_, '_, '_> { return Ok(Some(Type::any(span, Default::default()))); } - error!("({}) Failed to find type: {}{:?}", self.analyzer.scope.depth(), i.sym, i.span.ctxt); + error!( + "({}) Failed to find type: {}{:?}", + self.analyzer.scope.borrow().depth(), + i.sym, + i.span.ctxt + ); } // Handle enum variant type. @@ -2285,7 +2306,7 @@ impl Expander<'_, '_, '_> { Default::default(), ) .context("tried to access property as a part of type expansion") - .report(&mut self.analyzer.storage) + .report(&self.analyzer.storage) .unwrap_or_else(|| Type::any(span, Default::default())); return Ok(Some(ty)); } @@ -2298,7 +2319,7 @@ impl Expander<'_, '_, '_> { fn expand_ref(&mut self, r: Ref, was_top_level: bool) -> VResult> { let _tracing = dev_span!("Expander::expand_ref"); - let trying_primitive_expansion = self.analyzer.scope.expand_triage_depth != 0; + let trying_primitive_expansion = self.analyzer.scope.borrow_mut().expand_triage_depth != 0; let Ref { span: r_span, @@ -2359,16 +2380,16 @@ impl Expander<'_, '_, '_> { self.full |= matches!(ty, Type::Mapped(..)); - let trying_primitive_expansion = self.analyzer.scope.expand_triage_depth != 0; + let trying_primitive_expansion = self.analyzer.scope.borrow().expand_triage_depth != 0; // If we are trying to expand types as primitive, we ignore config let is_expansion_prevented = !trying_primitive_expansion && self.analyzer.is_expansion_prevented(&ty); - if self.analyzer.scope.expand_triage_depth != 0 { - self.analyzer.scope.expand_triage_depth += 1; + if self.analyzer.scope.borrow().expand_triage_depth != 0 { + self.analyzer.scope.borrow_mut().expand_triage_depth += 1; } - if self.analyzer.scope.expand_triage_depth > 30 { + if self.analyzer.scope.borrow().expand_triage_depth > 30 { return ty; } @@ -2383,15 +2404,15 @@ impl Expander<'_, '_, '_> { } } - if self.expand_top_level && self.analyzer.scope.expand_triage_depth == 0 { + if self.expand_top_level && self.analyzer.scope.borrow().expand_triage_depth == 0 { let old_full = self.full; - self.analyzer.scope.expand_triage_depth += 1; + self.analyzer.scope.borrow_mut().expand_triage_depth += 1; self.full = true; let candidate = ty.clone().fold_with(self); - self.analyzer.scope.expand_triage_depth = 0; + self.analyzer.scope.borrow_mut().expand_triage_depth = 0; self.full = old_full; return candidate; @@ -2746,7 +2767,7 @@ impl Fold for Expander<'_, '_, '_> { /// Calls [`Analyzer::normalize`] on top-level types pub struct ShallowNormalizer<'a, 'b, 'c> { - analyzer: &'a mut Analyzer<'b, 'c>, + analyzer: &'a Analyzer<'b, 'c>, } impl VisitMut for ShallowNormalizer<'_, '_, '_> { diff --git a/crates/stc_ts_file_analyzer/src/analyzer/scope/this.rs b/crates/stc_ts_file_analyzer/src/analyzer/scope/this.rs index 1bc7cac45b..94308dafec 100644 --- a/crates/stc_ts_file_analyzer/src/analyzer/scope/this.rs +++ b/crates/stc_ts_file_analyzer/src/analyzer/scope/this.rs @@ -9,9 +9,9 @@ use swc_common::Span; use crate::analyzer::Analyzer; impl Analyzer<'_, '_> { - pub(crate) fn get_property_type_from_this(&mut self, span: Span, p: &Id) -> Option { - if self.scope.is_this_ref_to_object_lit() || self.scope.is_this_ref_to_class() { - if let Some(declaring) = &self.scope.declaring_prop() { + pub(crate) fn get_property_type_from_this(&self, span: Span, p: &Id) -> Option { + if self.scope.borrow().is_this_ref_to_object_lit() || self.scope.borrow().is_this_ref_to_class() { + if let Some(declaring) = &self.scope.borrow().declaring_prop() { if *p.sym() == *declaring.sym() { return Some(Type::any( span, @@ -27,8 +27,8 @@ impl Analyzer<'_, '_> { } } - if self.scope.is_this_ref_to_class() { - for (_, m) in self.scope.class_members() { + if self.scope.borrow().is_this_ref_to_class() { + for (_, m) in self.scope.borrow().class_members() { match m { ClassMember::Method(Method { key: Key::Normal { sym, .. }, @@ -80,9 +80,9 @@ impl Analyzer<'_, '_> { /// Expand `this` contained in `ty`. pub(crate) fn expand_this_in_type(&mut self, ty: &mut Type) { - let this_ty = self.scope.this(); + let this_ty = self.scope.borrow().this().map(Cow::into_owned); - if let Some(this) = this_ty.map(Cow::into_owned) { + if let Some(this) = this_ty { ty.visit_mut_with(&mut ThisReplacer { this_ty: this, analyzer: self, diff --git a/crates/stc_ts_file_analyzer/src/analyzer/scope/type_param.rs b/crates/stc_ts_file_analyzer/src/analyzer/scope/type_param.rs index 41640cbd98..a3291c8d59 100644 --- a/crates/stc_ts_file_analyzer/src/analyzer/scope/type_param.rs +++ b/crates/stc_ts_file_analyzer/src/analyzer/scope/type_param.rs @@ -54,7 +54,7 @@ impl Analyzer<'_, '_> { ty.visit_mut_with(&mut v); } - fn is_type_param_dead(&mut self, name: &Id) -> bool { + fn is_type_param_dead(&self, name: &Id) -> bool { fn is_dead(s: &Scope, name: &Id) -> bool { if s.is_root() { return true; @@ -73,7 +73,7 @@ impl Analyzer<'_, '_> { } } - is_dead(&self.scope, name) + is_dead(&self.scope.borrow(), name) } } diff --git a/crates/stc_ts_file_analyzer/src/analyzer/stmt/loops.rs b/crates/stc_ts_file_analyzer/src/analyzer/stmt/loops.rs index 2a8771d52b..41ecb4d1b9 100644 --- a/crates/stc_ts_file_analyzer/src/analyzer/stmt/loops.rs +++ b/crates/stc_ts_file_analyzer/src/analyzer/stmt/loops.rs @@ -41,7 +41,7 @@ impl Analyzer<'_, '_> { let prev_false_facts = orig_facts.false_facts.take(); let mut facts_of_prev_body_eval = CondFacts::default(); let mut last = false; - let mut orig_vars = Some(self.scope.vars.clone()); + let mut orig_vars = Some(self.scope.borrow().vars.clone()); let mut max = 10; @@ -72,7 +72,7 @@ impl Analyzer<'_, '_> { }, |analyzer: &mut Analyzer| { if last { - analyzer.scope.vars = orig_vars.take().unwrap(); + analyzer.scope.borrow_mut().vars = orig_vars.take().unwrap(); } }, )?; @@ -99,7 +99,7 @@ impl Analyzer<'_, '_> { self.cur_facts.true_facts += prev_facts; self.cur_facts.false_facts += prev_false_facts; - if !self.scope.return_values.in_conditional { + if !self.scope.borrow().return_values.in_conditional { let mut v = LoopBreakerFinder { found: false }; body.visit_with(&mut v); let has_break = v.found; @@ -329,8 +329,8 @@ impl Analyzer<'_, '_> { vec![] } }; - debug_assert_eq!(child.scope.declaring, Vec::::new()); - child.scope.declaring.extend(created_vars); + debug_assert_eq!(child.scope.borrow().declaring, Vec::::new()); + child.scope.borrow_mut().declaring.extend(created_vars); child.ctx.allow_ref_declaring = matches!( left, @@ -412,7 +412,7 @@ impl Analyzer<'_, '_> { }; elem_ty.freeze(); - child.scope.declaring.clear(); + child.scope.borrow_mut().declaring.clear(); child.validate_lhs_of_for_loop(left, &elem_ty, kind); diff --git a/crates/stc_ts_file_analyzer/src/analyzer/stmt/mod.rs b/crates/stc_ts_file_analyzer/src/analyzer/stmt/mod.rs index ac744d1587..371fa2164e 100644 --- a/crates/stc_ts_file_analyzer/src/analyzer/stmt/mod.rs +++ b/crates/stc_ts_file_analyzer/src/analyzer/stmt/mod.rs @@ -50,12 +50,12 @@ impl Analyzer<'_, '_> { } } - let old_in_conditional = self.scope.return_values.in_conditional; - self.scope.return_values.in_conditional |= matches!(s, RStmt::If(_) | RStmt::Switch(_)); + let old_in_conditional = self.scope.borrow().return_values.in_conditional; + self.scope.borrow_mut().return_values.in_conditional |= matches!(s, RStmt::If(_) | RStmt::Switch(_)); s.visit_children_with(self); - self.scope.return_values.in_conditional = old_in_conditional; + self.scope.borrow_mut().return_values.in_conditional = old_in_conditional; let end = Instant::now(); @@ -77,7 +77,7 @@ impl Analyzer<'_, '_> { // Of `s` is always executed and we enter infinite loop, return type should be // never - if !self.scope.return_values.in_conditional { + if !self.scope.borrow().return_values.in_conditional { let mut v = LoopBreakerFinder { found: false }; body.visit_with(&mut v); let has_break = v.found; diff --git a/crates/stc_ts_file_analyzer/src/analyzer/stmt/return_type.rs b/crates/stc_ts_file_analyzer/src/analyzer/stmt/return_type.rs index 7c25c765e0..e1f9e59114 100644 --- a/crates/stc_ts_file_analyzer/src/analyzer/stmt/return_type.rs +++ b/crates/stc_ts_file_analyzer/src/analyzer/stmt/return_type.rs @@ -99,7 +99,7 @@ impl Analyzer<'_, '_> { self.with_ctx(ctx).with(|analyzer: &mut Analyzer| { analyzer.validate_stmts_and_collect(&stmts.iter().collect::>()); is_unreachable = analyzer.ctx.in_unreachable; - take(&mut analyzer.scope.return_values) + take(&mut analyzer.scope.get_mut().return_values) }) }; @@ -182,7 +182,7 @@ impl Analyzer<'_, '_> { } if types.is_empty() { - if let Some(declared) = self.scope.declared_return_type().cloned() { + if let Some(declared) = self.scope.borrow().declared_return_type().cloned() { // TODO(kdy1): Change this to `get_iterable_element_type` if let Ok(el_ty) = self.get_iterator_element_type(span, Cow::Owned(declared), true, Default::default()) { types.push(el_ty.into_owned()); @@ -296,7 +296,7 @@ impl Analyzer<'_, '_> { return Ok(ret_ty); } - if let Some(declared) = self.scope.declared_return_type().cloned() { + if let Some(declared) = self.scope.borrow().declared_return_type().cloned() { if !is_async && !is_generator { if ret_ty.is_none() && !is_unreachable { if let Type::Keyword(KeywordType { @@ -359,7 +359,7 @@ impl Analyzer<'_, '_> { }; let mut a = self.with_ctx(ctx); - let type_ann = a.scope.declared_return_type().cloned(); + let type_ann = a.scope.borrow().declared_return_type().cloned(); node.arg.validate_with_args(&mut *a, (TypeOfMode::RValue, None, type_ann.as_ref())) } { res? @@ -374,7 +374,7 @@ impl Analyzer<'_, '_> { debug_assert_ne!(ty.span(), DUMMY_SP, "{:?}", ty); ty.freeze(); - if let Some(declared) = self.scope.declared_return_type().cloned() { + if let Some(declared) = self.scope.borrow().declared_return_type().cloned() { let declared = Type::Instance(Instance { span: declared.span(), ty: Box::new(declared), @@ -481,7 +481,7 @@ impl Analyzer<'_, '_> { } } - self.scope.return_values.return_types.push(ty); + self.scope.borrow_mut().return_values.return_types.push(ty); Ok(()) } @@ -510,7 +510,7 @@ impl Analyzer<'_, '_> { } .freezed(); - if let Some(declared) = self.scope.declared_return_type().cloned() { + if let Some(declared) = self.scope.borrow().declared_return_type().cloned() { match if self.ctx.in_async { self.get_async_iterator_element_type(e.span, Cow::Owned(declared), true) .context("tried to get an element type from an async iterator for normal yield") @@ -561,9 +561,9 @@ impl Analyzer<'_, '_> { } } - self.scope.return_values.yield_types.push(item_ty); + self.scope.borrow_mut().return_values.yield_types.push(item_ty); } else { - self.scope.return_values.yield_types.push(Type::Keyword(KeywordType { + self.scope.borrow_mut().return_values.yield_types.push(Type::Keyword(KeywordType { span: e.span, kind: TsKeywordTypeKind::TsUndefinedKeyword, metadata: Default::default(), diff --git a/crates/stc_ts_file_analyzer/src/analyzer/stmt/var_decl.rs b/crates/stc_ts_file_analyzer/src/analyzer/stmt/var_decl.rs index 7b26444946..dfc7172ef7 100644 --- a/crates/stc_ts_file_analyzer/src/analyzer/stmt/var_decl.rs +++ b/crates/stc_ts_file_analyzer/src/analyzer/stmt/var_decl.rs @@ -92,13 +92,13 @@ impl Analyzer<'_, '_> { } let debug_declaring = if cfg!(debug_assertions) { - Some(self.scope.declaring.clone()) + Some(self.scope.borrow().declaring.clone()) } else { None }; let ids: Vec = find_ids_in_pat(&v.name); - let prev_declaring_len = self.scope.declaring.len(); - self.scope.declaring.extend(ids); + let prev_declaring_len = self.scope.borrow().declaring.len(); + self.scope.borrow_mut().declaring.extend(ids); macro_rules! inject_any { () => { @@ -138,8 +138,8 @@ impl Analyzer<'_, '_> { m.for_var_decls.entry(node_id).or_default().remove_init = true; } } - self.scope.declaring.drain(prev_declaring_len..); - debug_assert_eq!(Some(self.scope.declaring.clone()), debug_declaring); + self.scope.borrow_mut().declaring.drain(prev_declaring_len..); + debug_assert_eq!(Some(self.scope.borrow().declaring.clone()), debug_declaring); }}; } @@ -171,7 +171,11 @@ impl Analyzer<'_, '_> { // }; let creates_new_this = matches!(&**init, RExpr::Object(..)); - let old_this = if creates_new_this { self.scope.this.take() } else { None }; + let old_this = if creates_new_this { + self.scope.borrow_mut().this.take() + } else { + None + }; let declared_ty = v.name.get_ty(); let declared_ty_include_this = @@ -194,13 +198,13 @@ impl Analyzer<'_, '_> { match init.validate_with_args(self, (TypeOfMode::RValue, None, $ty)) { Ok(ty) => { if creates_new_this { - self.scope.this = old_this; + self.scope.borrow_mut().this = old_this; } ty.freezed() } Err(err) => { if creates_new_this { - self.scope.this = old_this; + self.scope.borrow_mut().this = old_this; } if self.config.is_builtin { unreachable!("failed to assign builtin: \nError: {:?}", err) @@ -262,7 +266,7 @@ impl Analyzer<'_, '_> { ty.freeze(); self.report_error_for_invalid_rvalue(span, &v.name, &ty); - self.scope.this = Some( + self.scope.borrow_mut().this = Some( if matches!( ty.normalize(), Type::Query(QueryType { @@ -275,10 +279,10 @@ impl Analyzer<'_, '_> { }) ) || self.ctx.in_class_member { - if self.scope.this().is_some() { - self.scope.this().unwrap().into_owned() + if self.scope.borrow().this().is_some() { + self.scope.borrow().this().unwrap().into_owned() } else { - if matches!(self.scope.kind(), ScopeKind::ArrowFn) { + if matches!(self.scope.borrow().kind(), ScopeKind::ArrowFn) { // ```ts // const Test8 = () => { // let x: typeof this.no = 1; @@ -466,7 +470,7 @@ impl Analyzer<'_, '_> { ty.assert_valid(); ty.freeze(); - if self.scope.is_root() { + if self.scope.borrow().is_root() { let ty = Some(forced_type_ann.unwrap_or_else(|| { let ty = ty.clone(); diff --git a/crates/stc_ts_file_analyzer/src/analyzer/tsc_helper.rs b/crates/stc_ts_file_analyzer/src/analyzer/tsc_helper.rs index 2585afe6c2..32db8f1b3b 100644 --- a/crates/stc_ts_file_analyzer/src/analyzer/tsc_helper.rs +++ b/crates/stc_ts_file_analyzer/src/analyzer/tsc_helper.rs @@ -12,7 +12,7 @@ use crate::VResult; /// These methods are ported from `tsc`. impl Analyzer<'_, '_> { /// `isTypeCloselyMatchedBy` of `tsc`. - pub(crate) fn is_type_closely_matched_by(&mut self, source: &Type, target: &Type) -> bool { + pub(crate) fn is_type_closely_matched_by(&self, source: &Type, target: &Type) -> bool { match (source.normalize(), target.normalize()) { (Type::Ref(source), Type::Ref(target)) => source.type_name.type_eq(&target.type_name), _ => false, @@ -27,17 +27,17 @@ impl Analyzer<'_, '_> { } /// `isTypeIdenticalTo` of `tsc`. - pub(crate) fn is_type_identical_to(&mut self, source: &Type, target: &Type) -> bool { + pub(crate) fn is_type_identical_to(&self, source: &Type, target: &Type) -> bool { self.is_type_related_to(source, target, Relation::Identity) } /// Ported from `isTypeAssignableTo` of `tsc`. - pub(crate) fn is_type_assignable_to(&mut self, span: Span, source: &Type, target: &Type) -> bool { + pub(crate) fn is_type_assignable_to(&self, span: Span, source: &Type, target: &Type) -> bool { self.assign(span, &mut Default::default(), target, source).is_ok() } /// Ported from `isValidNumberString` of `tsc`. - pub(crate) fn is_valid_num_str(&mut self, s: &str, round_trip_only: bool) -> bool { + pub(crate) fn is_valid_num_str(&self, s: &str, round_trip_only: bool) -> bool { if s.is_empty() { return false; } @@ -60,7 +60,7 @@ impl Analyzer<'_, '_> { } /// Ported from `isValidBigIntString` of `tsc`. - pub(crate) fn is_valid_big_int_str(&mut self, s: &str, round_trip_only: bool) -> bool { + pub(crate) fn is_valid_big_int_str(&self, s: &str, round_trip_only: bool) -> bool { if s.is_empty() { return false; } @@ -82,7 +82,7 @@ impl Analyzer<'_, '_> { } /// Ported from `isMemberOfStringMapping` of `tsc`. - pub(crate) fn is_member_of_string_mapping(&mut self, span: Span, source: &Type, target: &Type) -> VResult { + pub(crate) fn is_member_of_string_mapping(&self, span: Span, source: &Type, target: &Type) -> VResult { if target.is_any() || target.is_kwd(TsKeywordTypeKind::TsStringKeyword) { return Ok(true); } @@ -103,7 +103,7 @@ impl Analyzer<'_, '_> { Ok(false) } - pub(crate) fn get_string_like_type_for_type<'a>(&mut self, ty: &'a Type) -> Cow<'a, Type> { + pub(crate) fn get_string_like_type_for_type<'a>(&self, ty: &'a Type) -> Cow<'a, Type> { if ty.is_any() || ty.is_str() || ty.is_string_mapping() || ty.is_tpl() { Cow::Borrowed(ty) } else { diff --git a/crates/stc_ts_file_analyzer/src/analyzer/types/conditional.rs b/crates/stc_ts_file_analyzer/src/analyzer/types/conditional.rs index 469441332c..27f8594875 100644 --- a/crates/stc_ts_file_analyzer/src/analyzer/types/conditional.rs +++ b/crates/stc_ts_file_analyzer/src/analyzer/types/conditional.rs @@ -202,7 +202,7 @@ impl Analyzer<'_, '_> { } } - pub(crate) fn overwrite_conditional(&mut self, span: Span, c: &Conditional) -> Type { + pub(crate) fn overwrite_conditional(&self, span: Span, c: &Conditional) -> Type { if Self::has_type_param_for_conditional(&c.check_type) { if c.check_type.type_eq(&c.true_type) { Type::new_intersection(span, [*(c.check_type).clone(), *(c.extends_type).clone()]).freezed() @@ -227,7 +227,7 @@ impl Analyzer<'_, '_> { } } - pub(crate) fn expand_conditional_type(&mut self, span: Span, ty: Type) -> Type { + pub(crate) fn expand_conditional_type(&self, span: Span, ty: Type) -> Type { let _tracing = dev_span!("expand_conditional_type"); if !ty.is_conditional() { diff --git a/crates/stc_ts_file_analyzer/src/analyzer/types/keyof.rs b/crates/stc_ts_file_analyzer/src/analyzer/types/keyof.rs index 63bfd0336a..207360d5de 100644 --- a/crates/stc_ts_file_analyzer/src/analyzer/types/keyof.rs +++ b/crates/stc_ts_file_analyzer/src/analyzer/types/keyof.rs @@ -42,7 +42,7 @@ impl Analyzer<'_, '_> { /// k3 = '2'; // Error /// } /// ``` - pub(crate) fn keyof(&mut self, span: Span, ty: &Type) -> VResult { + pub(crate) fn keyof(&self, span: Span, ty: &Type) -> VResult { let span = span.with_ctxt(SyntaxContext::empty()); if !self.config.is_builtin { diff --git a/crates/stc_ts_file_analyzer/src/analyzer/types/mapped.rs b/crates/stc_ts_file_analyzer/src/analyzer/types/mapped.rs index 5452eff819..ca4aa495f5 100644 --- a/crates/stc_ts_file_analyzer/src/analyzer/types/mapped.rs +++ b/crates/stc_ts_file_analyzer/src/analyzer/types/mapped.rs @@ -35,7 +35,7 @@ impl Analyzer<'_, '_> { /// /// /// TODO(kdy1): Handle index signatures. - pub(crate) fn expand_mapped(&mut self, span: Span, m: &Mapped) -> VResult> { + pub(crate) fn expand_mapped(&self, span: Span, m: &Mapped) -> VResult> { let _guard = stack::track(span)?; let _tracing = dev_span!("expand_mapped"); @@ -54,7 +54,7 @@ impl Analyzer<'_, '_> { Ok(ty) } - fn expand_mapped_inner(&mut self, span: Span, m: &Mapped) -> VResult> { + fn expand_mapped_inner(&self, span: Span, m: &Mapped) -> VResult> { match m.type_param.constraint.as_deref().map(|v| v.normalize()) { Some(Type::Index(Index { ty: keyof_operand, .. })) => { return self.expand_mapped_type_with_keyof(span, keyof_operand, keyof_operand, m) @@ -135,7 +135,7 @@ impl Analyzer<'_, '_> { } fn expand_mapped_type_with_keyof( - &mut self, + &self, span: Span, keyof_operand: &Type, original_keyof_operand: &Type, @@ -436,7 +436,7 @@ impl Analyzer<'_, '_> { } /// TODO(kdy1): Optimize - fn expand_key_in_mapped(&mut self, mapped_type_param: Id, mapped_ty: &Type, key: &Key) -> VResult { + fn expand_key_in_mapped(&self, mapped_type_param: Id, mapped_ty: &Type, key: &Key) -> VResult { let mapped_ty = mapped_ty.clone(); let mut type_params = HashMap::default(); type_params.insert(mapped_type_param, key.ty().into_owned().freezed()); @@ -446,7 +446,7 @@ impl Analyzer<'_, '_> { /// Evaluate a type and convert it to keys. /// /// Used for types like `'foo' | 'bar'` or alias of them. - fn convert_type_to_keys_for_mapped_type(&mut self, span: Span, ty: &Type, name_type: Option<&Type>) -> VResult>> { + fn convert_type_to_keys_for_mapped_type(&self, span: Span, ty: &Type, name_type: Option<&Type>) -> VResult>> { let _tracing = dev_span!("convert_type_to_keys_for_mapped_type"); let _stack = stack::track(span)?; @@ -541,7 +541,7 @@ impl Analyzer<'_, '_> { /// Get keys of `ty` as a property name. pub(crate) fn get_property_names_for_mapped_type( - &mut self, + &self, span: Span, ty: &Type, type_param: &TypeParam, @@ -875,7 +875,7 @@ impl Analyzer<'_, '_> { } pub(crate) fn apply_mapped_flags_to_type( - &mut self, + &self, span: Span, ty: Type, optional: Option, diff --git a/crates/stc_ts_file_analyzer/src/analyzer/types/mod.rs b/crates/stc_ts_file_analyzer/src/analyzer/types/mod.rs index 244a0ef204..3b9aef8ed6 100644 --- a/crates/stc_ts_file_analyzer/src/analyzer/types/mod.rs +++ b/crates/stc_ts_file_analyzer/src/analyzer/types/mod.rs @@ -102,7 +102,7 @@ impl Analyzer<'_, '_> { /// /// If `span` is provided, it will be used for types **created** by the /// method. Otherwise the span of the original type is used. - pub(crate) fn normalize<'a>(&mut self, span: Option, mut ty: Cow<'a, Type>, opts: NormalizeTypeOpts) -> VResult> { + pub(crate) fn normalize<'a>(&self, span: Option, mut ty: Cow<'a, Type>, opts: NormalizeTypeOpts) -> VResult> { let _tracing = if cfg!(debug_assertions) { let ty = force_dump_type_as_string(&ty); @@ -797,7 +797,7 @@ impl Analyzer<'_, '_> { } } - pub(crate) fn normalize_intersection_types(&mut self, span: Span, types: &[Type], opts: NormalizeTypeOpts) -> VResult> { + pub(crate) fn normalize_intersection_types(&self, span: Span, types: &[Type], opts: NormalizeTypeOpts) -> VResult> { macro_rules! never { () => {{ Ok(Some(Type::Keyword(KeywordType { @@ -1197,7 +1197,7 @@ impl Analyzer<'_, '_> { } fn normalize_intersection_of_type_elements( - &mut self, + &self, span: Span, elements: &[TypeElement], property_types: &mut Vec, @@ -1252,7 +1252,7 @@ impl Analyzer<'_, '_> { } // This is part of normalization. - fn instantiate_for_normalization(&mut self, span: Option, ty: &Type, opts: NormalizeTypeOpts) -> VResult { + fn instantiate_for_normalization(&self, span: Option, ty: &Type, opts: NormalizeTypeOpts) -> VResult { let _tracing = if cfg!(debug_assertions) { let ty_str = force_dump_type_as_string(ty); @@ -1333,7 +1333,7 @@ impl Analyzer<'_, '_> { }) } - pub(crate) fn report_possibly_null_or_undefined(&mut self, span: Span, ty: &Type) -> VResult<()> { + pub(crate) fn report_possibly_null_or_undefined(&self, span: Span, ty: &Type) -> VResult<()> { let ty = self .normalize(Some(span), Cow::Borrowed(ty), Default::default()) .context("tried to normalize to see if it can be undefined")?; @@ -1395,7 +1395,7 @@ impl Analyzer<'_, '_> { } } - pub(crate) fn can_be_undefined(&mut self, span: Span, ty: &Type, include_null: bool) -> VResult { + pub(crate) fn can_be_undefined(&self, span: Span, ty: &Type, include_null: bool) -> VResult { let _tracing = dev_span!("can_be_undefined", include_null = include_null); let ty = self @@ -1441,7 +1441,7 @@ impl Analyzer<'_, '_> { }) } - pub(crate) fn expand_type_ann<'a>(&mut self, span: Span, ty: Option<&'a Type>) -> VResult>> { + pub(crate) fn expand_type_ann<'a>(&self, span: Span, ty: Option<&'a Type>) -> VResult>> { let _tracing = dev_span!("expand_type_ann"); let ty = match ty { @@ -1455,7 +1455,7 @@ impl Analyzer<'_, '_> { Ok(Some(ty)) } - pub(crate) fn create_prototype_of_class_def(&mut self, def: &ClassDef) -> VResult { + pub(crate) fn create_prototype_of_class_def(&self, def: &ClassDef) -> VResult { let _tracing = dev_span!("create_prototype_of_class_def"); let mut members = vec![]; @@ -1511,13 +1511,14 @@ impl Analyzer<'_, '_> { /// Exclude types from `ty` using type facts with key `name`, for /// the current scope. - pub(crate) fn exclude_types_using_fact(&mut self, span: Span, name: &Name, ty: &mut Type) { + pub(crate) fn exclude_types_using_fact(&self, span: Span, name: &Name, ty: &mut Type) { let _tracing = dev_span!("exclude_types_using_fact"); debug_assert!(!span.is_dummy(), "exclude_types should not be called with a dummy span"); let mut types_to_exclude = vec![]; - let mut s = Some(&self.scope); + let b = self.scope.borrow(); + let mut s = Some(&*b); while let Some(scope) = s { types_to_exclude.extend(scope.facts.excludes.get(name).cloned().into_iter().flatten()); @@ -1533,10 +1534,11 @@ impl Analyzer<'_, '_> { debug!("[types/facts] Excluded types: {} => {}", before, after); } - pub(crate) fn apply_type_facts(&mut self, name: &Name, ty: Type) -> Type { + pub(crate) fn apply_type_facts(&self, name: &Name, ty: Type) -> Type { let _tracing = dev_span!("apply_type_facts", name = tracing::field::debug(name)); - let type_facts = self.scope.get_type_facts(name) | self.cur_facts.true_facts.facts.get(name).copied().unwrap_or(TypeFacts::None); + let type_facts = + self.scope.borrow().get_type_facts(name) | self.cur_facts.true_facts.facts.get(name).copied().unwrap_or(TypeFacts::None); debug!("[types/fact] Facts for {:?} is {:?}", name, type_facts); @@ -1550,7 +1552,7 @@ impl Analyzer<'_, '_> { /// ## excluded /// /// Members of base class. - pub(crate) fn collect_class_members(&mut self, excluded: &[&ClassMember], ty: &Type) -> VResult>> { + pub(crate) fn collect_class_members(&self, excluded: &[&ClassMember], ty: &Type) -> VResult>> { if self.config.is_builtin { return Ok(None); } @@ -1604,7 +1606,7 @@ impl Analyzer<'_, '_> { /// Note: `span` is only used while expanding type (to prevent /// panic) in the case of [Type::Ref]. pub(crate) fn convert_type_to_type_lit<'a>( - &mut self, + &self, span: Span, ty: Cow<'a, Type>, opts: ConvertTypeToLitOpts, @@ -1916,7 +1918,7 @@ impl Analyzer<'_, '_> { })) } - fn merge_type_elements(&mut self, span: Span, mut els: Vec) -> VResult> { + fn merge_type_elements(&self, span: Span, mut els: Vec) -> VResult> { run(|| { // As merging is not common, we optimize it by creating a new vector only if // there's a conflict @@ -1970,7 +1972,7 @@ impl Analyzer<'_, '_> { .with_context(|| "tried to merge type elements".to_string()) } - fn merge_type_element(&mut self, span: Span, to: &mut TypeElement, from: TypeElement) -> VResult<()> { + fn merge_type_element(&self, span: Span, to: &mut TypeElement, from: TypeElement) -> VResult<()> { run(|| match (to, from) { (TypeElement::Property(to), TypeElement::Property(from)) => { if let Some(to_type) = &to.type_ann { @@ -2039,7 +2041,7 @@ impl Analyzer<'_, '_> { v } - pub(crate) fn expand_intrinsic_types(&mut self, span: Span, ty: &StringMapping, span_for_validation: Span) -> VResult { + pub(crate) fn expand_intrinsic_types(&self, span: Span, ty: &StringMapping, span_for_validation: Span) -> VResult { let arg = &ty.type_args; let normalized_ty = match self @@ -2243,7 +2245,7 @@ impl Analyzer<'_, '_> { } pub(crate) fn report_error_for_unresolved_type( - &mut self, + &self, span: Span, type_name: &RExpr, type_args: Option<&TypeParamInstantiation>, @@ -2369,7 +2371,7 @@ impl Analyzer<'_, '_> { /// // To use the fact that `a` is not `P`, we check for the parent type of `ty /// } /// ``` - fn exclude_type(&mut self, span: Span, ty: &mut Type, excluded: &Type) { + fn exclude_type(&self, span: Span, ty: &mut Type, excluded: &Type) { let span = span.with_ctxt(SyntaxContext::empty()); if ty.type_eq(excluded) { @@ -2485,7 +2487,7 @@ impl Analyzer<'_, '_> { } } - fn exclude_types(&mut self, span: Span, ty: &mut Type, excludes: Option>) { + fn exclude_types(&self, span: Span, ty: &mut Type, excludes: Option>) { ty.freeze(); let mapped_ty = self.normalize( diff --git a/crates/stc_ts_file_analyzer/src/analyzer/types/narrowing.rs b/crates/stc_ts_file_analyzer/src/analyzer/types/narrowing.rs index b3353044fe..6cf0d2894d 100644 --- a/crates/stc_ts_file_analyzer/src/analyzer/types/narrowing.rs +++ b/crates/stc_ts_file_analyzer/src/analyzer/types/narrowing.rs @@ -13,7 +13,7 @@ use crate::{ }; impl Analyzer<'_, '_> { - pub(crate) fn narrowed_type_of_assignment(&mut self, span: Span, declared: Type, actual: &Type) -> VResult { + pub(crate) fn narrowed_type_of_assignment(&self, span: Span, declared: Type, actual: &Type) -> VResult { declared.assert_valid(); actual.assert_valid(); diff --git a/crates/stc_ts_file_analyzer/src/analyzer/util.rs b/crates/stc_ts_file_analyzer/src/analyzer/util.rs index 606195a336..83c7217840 100644 --- a/crates/stc_ts_file_analyzer/src/analyzer/util.rs +++ b/crates/stc_ts_file_analyzer/src/analyzer/util.rs @@ -301,7 +301,7 @@ pub trait ResultExt: Into> { } } - fn report(self, storage: &mut Storage) -> Option { + fn report(self, storage: &Storage) -> Option { match self.into() { Ok(v) => Some(v), Err(err) => { diff --git a/crates/stc_ts_file_analyzer/src/ty/type_facts.rs b/crates/stc_ts_file_analyzer/src/ty/type_facts.rs index b64aeaebf4..06ab825512 100644 --- a/crates/stc_ts_file_analyzer/src/ty/type_facts.rs +++ b/crates/stc_ts_file_analyzer/src/ty/type_facts.rs @@ -25,7 +25,7 @@ impl Analyzer<'_, '_> { /// Those are preserved if /// /// - it's Promise - pub fn apply_type_facts_to_type(&mut self, facts: TypeFacts, mut ty: Type) -> Type { + pub fn apply_type_facts_to_type(&self, facts: TypeFacts, mut ty: Type) -> Type { if self.config.is_builtin { return ty; } @@ -156,7 +156,7 @@ impl Analyzer<'_, '_> { struct TypeFactsHandler<'a, 'b, 'c> { /// Used to expand references. - analyzer: &'a mut Analyzer<'b, 'c>, + analyzer: &'a Analyzer<'b, 'c>, facts: TypeFacts, } diff --git a/crates/stc_ts_storage/src/lib.rs b/crates/stc_ts_storage/src/lib.rs index 5b65974929..045cf1fa80 100644 --- a/crates/stc_ts_storage/src/lib.rs +++ b/crates/stc_ts_storage/src/lib.rs @@ -1,4 +1,8 @@ -use std::{collections::hash_map::Entry, mem::take, sync::Arc}; +use std::{ + collections::hash_map::Entry, + mem::take, + sync::{Arc, Mutex}, +}; use auto_impl::auto_impl; use fxhash::FxHashMap; @@ -10,7 +14,7 @@ use swc_common::{iter::IdentifyLast, FileName, Span, SyntaxContext, TypeEq, DUMM #[derive(Debug, Default)] pub struct Info { - pub errors: Errors, + pub errors: Mutex, pub exports: ModuleTypeData, } @@ -18,9 +22,9 @@ pub type Storage<'b> = Box; #[auto_impl(&mut, Box)] pub trait ErrorStore { - fn report(&mut self, err: Error); - fn report_all(&mut self, err: Errors); - fn take_errors(&mut self) -> Errors; + fn report(&self, err: Error); + fn report_all(&self, err: Errors); + fn take_errors(&self) -> Errors; } #[auto_impl(&mut, Box)] @@ -58,7 +62,7 @@ pub trait Mode: TypeStore + ErrorStore { fn subscope(&self) -> Storage; fn merge_back(&mut self, subscope: Storage) { - let mut ss = subscope; + let ss = subscope; let errors = ss.take_errors(); self.report_all(errors); } @@ -75,16 +79,16 @@ pub struct Single<'a> { } impl ErrorStore for Single<'_> { - fn report(&mut self, err: Error) { - self.info.errors.push(err); + fn report(&self, err: Error) { + self.info.errors.lock().unwrap().push(err); } - fn report_all(&mut self, err: Errors) { - self.info.errors.extend(err); + fn report_all(&self, err: Errors) { + self.info.errors.lock().unwrap().extend(err); } - fn take_errors(&mut self) -> Errors { - take(&mut self.info.errors) + fn take_errors(&self) -> Errors { + take(&mut self.info.errors.lock().unwrap()) } } @@ -230,21 +234,21 @@ pub struct File { pub struct Group<'a> { pub parent: Option<&'a Group<'a>>, pub files: Arc>, - pub errors: Errors, + pub errors: Mutex, pub info: FxHashMap, } impl ErrorStore for Group<'_> { - fn report(&mut self, err: Error) { - self.errors.push(err); + fn report(&self, err: Error) { + self.errors.lock().unwrap().push(err); } - fn report_all(&mut self, err: Errors) { - self.errors.extend(err); + fn report_all(&self, err: Errors) { + self.errors.lock().unwrap().extend(err); } - fn take_errors(&mut self) -> Errors { - take(&mut self.errors) + fn take_errors(&self) -> Errors { + take(&mut self.errors.lock().unwrap()) } } @@ -391,18 +395,18 @@ pub struct Builtin { } impl ErrorStore for Builtin { - fn report(&mut self, err: Error) { + fn report(&self, err: Error) { unreachable!("builtin error: {:?}", err); } - fn report_all(&mut self, err: Errors) { + fn report_all(&self, err: Errors) { if err.is_empty() { return; } unreachable!("builtin error: {:?}", err); } - fn take_errors(&mut self) -> Errors { + fn take_errors(&self) -> Errors { Default::default() } } diff --git a/crates/stc_ts_type_cache/src/cache_map.rs b/crates/stc_ts_type_cache/src/cache_map.rs index 1d92cdad95..8f8451d6ef 100644 --- a/crates/stc_ts_type_cache/src/cache_map.rs +++ b/crates/stc_ts_type_cache/src/cache_map.rs @@ -1,4 +1,4 @@ -use std::marker::PhantomData; +use std::{cell::RefCell, marker::PhantomData}; use stc_utils::cache::Freeze; use swc_common::TypeEq; @@ -12,7 +12,7 @@ where V: Freeze, M: CacheMode, { - data: Vec<(K, V)>, + data: RefCell>, _marker: PhantomData, } @@ -42,7 +42,7 @@ where } pub fn get(&self, key: &K) -> Option { - for (k, v) in &self.data { + for (k, v) in &*self.data.borrow() { if k.type_eq(key) { return Some(v.clone()); } @@ -52,10 +52,10 @@ where } /// Returns the inserted value. - pub fn insert(&mut self, key: K, mut value: V) -> V { + pub fn insert(&self, key: K, mut value: V) -> V { value.freeze(); - self.data.push((key, value.clone())); + self.data.borrow_mut().push((key, value.clone())); value }