diff --git a/crates/oxc_ast/src/ast/ts.rs b/crates/oxc_ast/src/ast/ts.rs index 49bdf0c96b9a6..9faf23f7a4e00 100644 --- a/crates/oxc_ast/src/ast/ts.rs +++ b/crates/oxc_ast/src/ast/ts.rs @@ -282,7 +282,9 @@ pub use match_ts_type; /// ## Reference /// * [TypeScript Handbook - Conditional Types](https://www.typescriptlang.org/docs/handbook/2/conditional-types.html) #[ast(visit)] -#[scope] +#[scope( + flags = ScopeFlags::TsConditional, +)] #[derive(Debug)] #[generate_derive(CloneIn, GetSpan, GetSpanMut, ContentEq, ESTree)] pub struct TSConditionalType<'a> { diff --git a/crates/oxc_ast_visit/src/generated/visit.rs b/crates/oxc_ast_visit/src/generated/visit.rs index 2e9b75e161df1..bd9be6bc6d2a8 100644 --- a/crates/oxc_ast_visit/src/generated/visit.rs +++ b/crates/oxc_ast_visit/src/generated/visit.rs @@ -3302,7 +3302,7 @@ pub mod walk { visitor.enter_node(kind); visitor.visit_span(&it.span); visitor.visit_ts_type(&it.check_type); - visitor.enter_scope(ScopeFlags::empty(), &it.scope_id); + visitor.enter_scope(ScopeFlags::TsConditional, &it.scope_id); visitor.visit_ts_type(&it.extends_type); visitor.visit_ts_type(&it.true_type); visitor.leave_scope(); diff --git a/crates/oxc_ast_visit/src/generated/visit_mut.rs b/crates/oxc_ast_visit/src/generated/visit_mut.rs index b7f5a148f7526..f7382bce07317 100644 --- a/crates/oxc_ast_visit/src/generated/visit_mut.rs +++ b/crates/oxc_ast_visit/src/generated/visit_mut.rs @@ -3466,7 +3466,7 @@ pub mod walk_mut { visitor.enter_node(kind); visitor.visit_span(&mut it.span); visitor.visit_ts_type(&mut it.check_type); - visitor.enter_scope(ScopeFlags::empty(), &it.scope_id); + visitor.enter_scope(ScopeFlags::TsConditional, &it.scope_id); visitor.visit_ts_type(&mut it.extends_type); visitor.visit_ts_type(&mut it.true_type); visitor.leave_scope(); diff --git a/crates/oxc_semantic/src/binder.rs b/crates/oxc_semantic/src/binder.rs index 2d3359d686fec..5da592326bb93 100644 --- a/crates/oxc_semantic/src/binder.rs +++ b/crates/oxc_semantic/src/binder.rs @@ -439,9 +439,22 @@ impl<'a> Binder<'a> for TSModuleDeclaration<'a> { impl<'a> Binder<'a> for TSTypeParameter<'a> { fn bind(&self, builder: &mut SemanticBuilder) { - let symbol_id = builder.declare_symbol( + let scope_id = if matches!( + builder.nodes.parent_kind(builder.current_node_id), + Some(AstKind::TSInferType(_)) + ) { + builder + .scope + .ancestors(builder.current_scope_id) + .find(|scope_id| builder.scope.get_flags(*scope_id).is_ts_conditional()) + } else { + None + }; + + let symbol_id = builder.declare_symbol_on_scope( self.name.span, &self.name.name, + scope_id.unwrap_or(builder.current_scope_id), SymbolFlags::TypeParameter, SymbolFlags::TypeParameterExcludes, ); diff --git a/crates/oxc_semantic/tests/fixtures/typescript-eslint/type-declaration/conditional-nested.snap b/crates/oxc_semantic/tests/fixtures/typescript-eslint/type-declaration/conditional-nested.snap index fcaff3fb0c93b..02ec9300efdc5 100644 --- a/crates/oxc_semantic/tests/fixtures/typescript-eslint/type-declaration/conditional-nested.snap +++ b/crates/oxc_semantic/tests/fixtures/typescript-eslint/type-declaration/conditional-nested.snap @@ -9,7 +9,7 @@ input_file: crates/oxc_semantic/tests/fixtures/typescript-eslint/type-declaratio "children": [ { "children": [], - "flags": "ScopeFlags(StrictMode)", + "flags": "ScopeFlags(StrictMode | TsConditional)", "id": 2, "node": "TSConditionalType", "symbols": [ @@ -31,7 +31,7 @@ input_file: crates/oxc_semantic/tests/fixtures/typescript-eslint/type-declaratio }, { "children": [], - "flags": "ScopeFlags(StrictMode)", + "flags": "ScopeFlags(StrictMode | TsConditional)", "id": 3, "node": "TSConditionalType", "symbols": [ diff --git a/crates/oxc_semantic/tests/fixtures/typescript-eslint/type-declaration/conditional1.snap b/crates/oxc_semantic/tests/fixtures/typescript-eslint/type-declaration/conditional1.snap index 4f0e710a2d724..e66568b957bb9 100644 --- a/crates/oxc_semantic/tests/fixtures/typescript-eslint/type-declaration/conditional1.snap +++ b/crates/oxc_semantic/tests/fixtures/typescript-eslint/type-declaration/conditional1.snap @@ -9,7 +9,7 @@ input_file: crates/oxc_semantic/tests/fixtures/typescript-eslint/type-declaratio "children": [ { "children": [], - "flags": "ScopeFlags(StrictMode)", + "flags": "ScopeFlags(StrictMode | TsConditional)", "id": 2, "node": "TSConditionalType", "symbols": [ diff --git a/crates/oxc_semantic/tests/fixtures/typescript-eslint/type-declaration/conditional2.snap b/crates/oxc_semantic/tests/fixtures/typescript-eslint/type-declaration/conditional2.snap index e6f00641c36c7..96cd7fed52dcf 100644 --- a/crates/oxc_semantic/tests/fixtures/typescript-eslint/type-declaration/conditional2.snap +++ b/crates/oxc_semantic/tests/fixtures/typescript-eslint/type-declaration/conditional2.snap @@ -9,7 +9,7 @@ input_file: crates/oxc_semantic/tests/fixtures/typescript-eslint/type-declaratio "children": [ { "children": [], - "flags": "ScopeFlags(StrictMode)", + "flags": "ScopeFlags(StrictMode | TsConditional)", "id": 2, "node": "TSConditionalType", "symbols": [ diff --git a/crates/oxc_semantic/tests/fixtures/typescript-eslint/type-declaration/conditional3.snap b/crates/oxc_semantic/tests/fixtures/typescript-eslint/type-declaration/conditional3.snap index 91f4ae635b63f..d200ae366eee1 100644 --- a/crates/oxc_semantic/tests/fixtures/typescript-eslint/type-declaration/conditional3.snap +++ b/crates/oxc_semantic/tests/fixtures/typescript-eslint/type-declaration/conditional3.snap @@ -9,7 +9,7 @@ input_file: crates/oxc_semantic/tests/fixtures/typescript-eslint/type-declaratio "children": [ { "children": [], - "flags": "ScopeFlags(StrictMode)", + "flags": "ScopeFlags(StrictMode | TsConditional)", "id": 2, "node": "TSConditionalType", "symbols": [ diff --git a/crates/oxc_semantic/tests/fixtures/typescript-eslint/type-declaration/conditional4.snap b/crates/oxc_semantic/tests/fixtures/typescript-eslint/type-declaration/conditional4.snap index 54353842b0fa9..af6c105121b8b 100644 --- a/crates/oxc_semantic/tests/fixtures/typescript-eslint/type-declaration/conditional4.snap +++ b/crates/oxc_semantic/tests/fixtures/typescript-eslint/type-declaration/conditional4.snap @@ -9,7 +9,7 @@ input_file: crates/oxc_semantic/tests/fixtures/typescript-eslint/type-declaratio "children": [ { "children": [], - "flags": "ScopeFlags(StrictMode)", + "flags": "ScopeFlags(StrictMode | TsConditional)", "id": 2, "node": "TSConditionalType", "symbols": [ diff --git a/crates/oxc_semantic/tests/fixtures/typescript-eslint/type-declaration/conditional5.snap b/crates/oxc_semantic/tests/fixtures/typescript-eslint/type-declaration/conditional5.snap index 2f0712164f7ba..be040473eec1f 100644 --- a/crates/oxc_semantic/tests/fixtures/typescript-eslint/type-declaration/conditional5.snap +++ b/crates/oxc_semantic/tests/fixtures/typescript-eslint/type-declaration/conditional5.snap @@ -9,7 +9,7 @@ input_file: crates/oxc_semantic/tests/fixtures/typescript-eslint/type-declaratio "children": [ { "children": [], - "flags": "ScopeFlags(StrictMode)", + "flags": "ScopeFlags(StrictMode | TsConditional)", "id": 2, "node": "TSConditionalType", "symbols": [ diff --git a/crates/oxc_semantic/tests/fixtures/typescript-eslint/type-declaration/infer-type-constraint.snap b/crates/oxc_semantic/tests/fixtures/typescript-eslint/type-declaration/infer-type-constraint.snap index 73df8fe8ff0d4..bf3599377341c 100644 --- a/crates/oxc_semantic/tests/fixtures/typescript-eslint/type-declaration/infer-type-constraint.snap +++ b/crates/oxc_semantic/tests/fixtures/typescript-eslint/type-declaration/infer-type-constraint.snap @@ -16,7 +16,7 @@ input_file: crates/oxc_semantic/tests/fixtures/typescript-eslint/type-declaratio "children": [ { "children": [], - "flags": "ScopeFlags(StrictMode)", + "flags": "ScopeFlags(StrictMode | TsConditional)", "id": 3, "node": "TSConditionalType", "symbols": [ diff --git a/crates/oxc_syntax/src/scope.rs b/crates/oxc_syntax/src/scope.rs index 6a39d5075eeb3..a35cfad14ae7d 100644 --- a/crates/oxc_syntax/src/scope.rs +++ b/crates/oxc_syntax/src/scope.rs @@ -77,6 +77,7 @@ bitflags! { const SetAccessor = 1 << 8; const CatchClause = 1 << 9; const DirectEval = 1 << 10; // + const TsConditional = 1 << 11; const Var = Self::Top.bits() | Self::Function.bits() | Self::ClassStaticBlock.bits() | Self::TsModuleBlock.bits(); } } @@ -148,6 +149,10 @@ impl ScopeFlags { self.contains(Self::CatchClause) } + pub fn is_ts_conditional(&self) -> bool { + self.contains(Self::TsConditional) + } + #[inline] pub fn contains_direct_eval(&self) -> bool { self.contains(Self::DirectEval) diff --git a/tasks/coverage/snapshots/semantic_typescript.snap b/tasks/coverage/snapshots/semantic_typescript.snap index 83149658ef039..ca870d4d43a86 100644 --- a/tasks/coverage/snapshots/semantic_typescript.snap +++ b/tasks/coverage/snapshots/semantic_typescript.snap @@ -13901,7 +13901,7 @@ semantic error: Scope children mismatch: after transform: ScopeId(0): [ScopeId(1), ScopeId(6), ScopeId(7)] rebuilt : ScopeId(0): [] Unresolved references mismatch: -after transform: ["Pick", "U"] +after transform: ["Pick"] rebuilt : [] tasks/coverage/typescript/tests/cases/compiler/inferFromGenericFunctionReturnTypes2.ts @@ -41049,9 +41049,6 @@ tasks/coverage/typescript/tests/cases/conformance/types/conditional/inferTypes2. semantic error: Scope children mismatch: after transform: ScopeId(0): [ScopeId(1), ScopeId(3), ScopeId(4), ScopeId(6), ScopeId(9), ScopeId(10), ScopeId(12)] rebuilt : ScopeId(0): [ScopeId(1), ScopeId(2)] -Unresolved references mismatch: -after transform: ["P", "foo", "foo2"] -rebuilt : ["foo", "foo2"] tasks/coverage/typescript/tests/cases/conformance/types/conditional/inferTypesWithExtends1.ts semantic error: Bindings mismatch: