Skip to content

Commit a39a9cc

Browse files
committed
Merge remote-tracking branch 'origin/main' into dcreager/better-constraint-copies
* origin/main: [red-knot] Prevent cross-module query dependencies in `own_instance_member` (#16268) Specify the `wasm-pack` version for release workflows (#16278) [red-knot] Separate `definitions_by_definition` into separate fields (#16277)
2 parents fc78683 + 470f852 commit a39a9cc

File tree

11 files changed

+185
-104
lines changed

11 files changed

+185
-104
lines changed

.github/workflows/publish-playground.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ jobs:
3535
cache: "npm"
3636
cache-dependency-path: playground/package-lock.json
3737
- uses: jetli/wasm-pack-action@v0.4.0
38+
with:
39+
version: v0.13.1
3840
- uses: jetli/wasm-bindgen-action@v0.2.0
3941
- name: "Run wasm-pack"
4042
run: wasm-pack build --target web --out-dir ../../playground/src/pkg crates/ruff_wasm

.github/workflows/publish-wasm.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ jobs:
3535
- name: "Install Rust toolchain"
3636
run: rustup target add wasm32-unknown-unknown
3737
- uses: jetli/wasm-pack-action@v0.4.0
38+
with:
39+
version: v0.13.1
3840
- uses: jetli/wasm-bindgen-action@v0.2.0
3941
- name: "Run wasm-pack build"
4042
run: wasm-pack build --target ${{ matrix.target }} crates/ruff_wasm

crates/red_knot_python_semantic/src/semantic_index/builder.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,12 +346,14 @@ impl<'db> SemanticIndexBuilder<'db> {
346346
// SAFETY: `definition_node` is guaranteed to be a child of `self.module`
347347
let kind = unsafe { definition_node.into_owned(self.module.clone()) };
348348
let category = kind.category();
349+
let is_reexported = kind.is_reexported();
349350
let definition = Definition::new(
350351
self.db,
351352
self.file,
352353
self.current_scope(),
353354
symbol,
354355
kind,
356+
is_reexported,
355357
countme::Count::default(),
356358
);
357359

crates/red_knot_python_semantic/src/semantic_index/definition.rs

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -33,34 +33,23 @@ pub struct Definition<'db> {
3333
/// The symbol defined.
3434
pub(crate) symbol: ScopedSymbolId,
3535

36+
/// WARNING: Only access this field when doing type inference for the same
37+
/// file as where `Definition` is defined to avoid cross-file query dependencies.
3638
#[no_eq]
3739
#[return_ref]
3840
#[tracked]
3941
pub(crate) kind: DefinitionKind<'db>,
4042

43+
/// This is a dedicated field to avoid accessing `kind` to compute this value.
44+
pub(crate) is_reexported: bool,
45+
4146
count: countme::Count<Definition<'static>>,
4247
}
4348

4449
impl<'db> Definition<'db> {
4550
pub(crate) fn scope(self, db: &'db dyn Db) -> ScopeId<'db> {
4651
self.file_scope(db).to_scope_id(db, self.file(db))
4752
}
48-
49-
pub(crate) fn category(self, db: &'db dyn Db) -> DefinitionCategory {
50-
self.kind(db).category()
51-
}
52-
53-
pub(crate) fn is_declaration(self, db: &'db dyn Db) -> bool {
54-
self.kind(db).category().is_declaration()
55-
}
56-
57-
pub(crate) fn is_binding(self, db: &'db dyn Db) -> bool {
58-
self.kind(db).category().is_binding()
59-
}
60-
61-
pub(crate) fn is_reexported(self, db: &'db dyn Db) -> bool {
62-
self.kind(db).is_reexported()
63-
}
6453
}
6554

6655
#[derive(Copy, Clone, Debug)]

crates/red_knot_python_semantic/src/semantic_index/use_def.rs

Lines changed: 28 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -293,19 +293,22 @@ pub(crate) struct UseDefMap<'db> {
293293
/// [`SymbolBindings`] reaching a [`ScopedUseId`].
294294
bindings_by_use: IndexVec<ScopedUseId, SymbolBindings>,
295295

296-
/// [`SymbolBindings`] or [`SymbolDeclarations`] reaching a given [`Definition`].
297-
///
298296
/// If the definition is a binding (only) -- `x = 1` for example -- then we need
299297
/// [`SymbolDeclarations`] to know whether this binding is permitted by the live declarations.
300298
///
299+
/// If the definition is both a declaration and a binding -- `x: int = 1` for example -- then
300+
/// we don't actually need anything here, all we'll need to validate is that our own RHS is a
301+
/// valid assignment to our own annotation.
302+
declarations_by_binding: FxHashMap<Definition<'db>, SymbolDeclarations>,
303+
301304
/// If the definition is a declaration (only) -- `x: int` for example -- then we need
302305
/// [`SymbolBindings`] to know whether this declaration is consistent with the previously
303306
/// inferred type.
304307
///
305308
/// If the definition is both a declaration and a binding -- `x: int = 1` for example -- then
306309
/// we don't actually need anything here, all we'll need to validate is that our own RHS is a
307310
/// valid assignment to our own annotation.
308-
definitions_by_definition: FxHashMap<Definition<'db>, SymbolDefinitions>,
311+
bindings_by_declaration: FxHashMap<Definition<'db>, SymbolBindings>,
309312

310313
/// [`SymbolState`] visible at end of scope for each symbol.
311314
public_symbols: IndexVec<ScopedSymbolId, SymbolState>,
@@ -343,25 +346,14 @@ impl<'db> UseDefMap<'db> {
343346
&self,
344347
declaration: Definition<'db>,
345348
) -> BindingWithConstraintsIterator<'_, 'db> {
346-
if let SymbolDefinitions::Bindings(bindings) = &self.definitions_by_definition[&declaration]
347-
{
348-
self.bindings_iterator(bindings)
349-
} else {
350-
unreachable!("Declaration has non-Bindings in definitions_by_definition");
351-
}
349+
self.bindings_iterator(&self.bindings_by_declaration[&declaration])
352350
}
353351

354-
pub(crate) fn declarations_at_binding<'map>(
355-
&'map self,
352+
pub(crate) fn declarations_at_binding(
353+
&self,
356354
binding: Definition<'db>,
357-
) -> DeclarationsIterator<'map, 'db> {
358-
if let SymbolDefinitions::Declarations(declarations) =
359-
&self.definitions_by_definition[&binding]
360-
{
361-
self.declarations_iterator(declarations)
362-
} else {
363-
unreachable!("Binding has non-Declarations in definitions_by_definition");
364-
}
355+
) -> DeclarationsIterator<'_, 'db> {
356+
self.declarations_iterator(&self.declarations_by_binding[&binding])
365357
}
366358

367359
pub(crate) fn public_declarations<'map>(
@@ -421,13 +413,6 @@ pub(crate) struct EagerBindingsKey {
421413
/// A snapshot of bindings that can be used to resolve a reference in a nested eager scope.
422414
type EagerBindings = IndexVec<ScopedEagerBindingsId, SymbolBindings>;
423415

424-
/// Either live bindings or live declarations for a symbol.
425-
#[derive(Debug, PartialEq, Eq, salsa::Update)]
426-
enum SymbolDefinitions {
427-
Bindings(SymbolBindings),
428-
Declarations(SymbolDeclarations),
429-
}
430-
431416
#[derive(Debug)]
432417
pub(crate) struct BindingWithConstraintsIterator<'map, 'db> {
433418
all_definitions: &'map IndexVec<ScopedDefinitionId, Option<Definition<'db>>>,
@@ -539,8 +524,11 @@ pub(super) struct UseDefMapBuilder<'db> {
539524
/// Live bindings at each so-far-recorded use.
540525
bindings_by_use: IndexVec<ScopedUseId, SymbolBindings>,
541526

542-
/// Live bindings or declarations for each so-far-recorded definition.
543-
definitions_by_definition: FxHashMap<Definition<'db>, SymbolDefinitions>,
527+
/// Live declarations for each so-far-recorded binding.
528+
declarations_by_binding: FxHashMap<Definition<'db>, SymbolDeclarations>,
529+
530+
/// Live bindings for each so-far-recorded declaration.
531+
bindings_by_declaration: FxHashMap<Definition<'db>, SymbolBindings>,
544532

545533
/// Currently live bindings and declarations for each symbol.
546534
symbol_states: IndexVec<ScopedSymbolId, SymbolState>,
@@ -558,7 +546,8 @@ impl Default for UseDefMapBuilder<'_> {
558546
visibility_constraints: VisibilityConstraintsBuilder::default(),
559547
scope_start_visibility: ScopedVisibilityConstraintId::ALWAYS_TRUE,
560548
bindings_by_use: IndexVec::new(),
561-
definitions_by_definition: FxHashMap::default(),
549+
declarations_by_binding: FxHashMap::default(),
550+
bindings_by_declaration: FxHashMap::default(),
562551
symbol_states: IndexVec::new(),
563552
eager_bindings: EagerBindings::default(),
564553
}
@@ -580,10 +569,8 @@ impl<'db> UseDefMapBuilder<'db> {
580569
pub(super) fn record_binding(&mut self, symbol: ScopedSymbolId, binding: Definition<'db>) {
581570
let def_id = self.all_definitions.push(Some(binding));
582571
let symbol_state = &mut self.symbol_states[symbol];
583-
self.definitions_by_definition.insert(
584-
binding,
585-
SymbolDefinitions::Declarations(symbol_state.declarations().clone()),
586-
);
572+
self.declarations_by_binding
573+
.insert(binding, symbol_state.declarations().clone());
587574
symbol_state.record_binding(def_id, self.scope_start_visibility);
588575
}
589576

@@ -660,10 +647,8 @@ impl<'db> UseDefMapBuilder<'db> {
660647
) {
661648
let def_id = self.all_definitions.push(Some(declaration));
662649
let symbol_state = &mut self.symbol_states[symbol];
663-
self.definitions_by_definition.insert(
664-
declaration,
665-
SymbolDefinitions::Bindings(symbol_state.bindings().clone()),
666-
);
650+
self.bindings_by_declaration
651+
.insert(declaration, symbol_state.bindings().clone());
667652
symbol_state.record_declaration(def_id);
668653
}
669654

@@ -672,7 +657,8 @@ impl<'db> UseDefMapBuilder<'db> {
672657
symbol: ScopedSymbolId,
673658
definition: Definition<'db>,
674659
) {
675-
// We don't need to store anything in self.definitions_by_definition.
660+
// We don't need to store anything in self.bindings_by_declaration or
661+
// self.declarations_by_binding.
676662
let def_id = self.all_definitions.push(Some(definition));
677663
let symbol_state = &mut self.symbol_states[symbol];
678664
symbol_state.record_declaration(def_id);
@@ -771,7 +757,8 @@ impl<'db> UseDefMapBuilder<'db> {
771757
self.all_definitions.shrink_to_fit();
772758
self.symbol_states.shrink_to_fit();
773759
self.bindings_by_use.shrink_to_fit();
774-
self.definitions_by_definition.shrink_to_fit();
760+
self.declarations_by_binding.shrink_to_fit();
761+
self.bindings_by_declaration.shrink_to_fit();
775762
self.eager_bindings.shrink_to_fit();
776763

777764
UseDefMap {
@@ -780,7 +767,8 @@ impl<'db> UseDefMapBuilder<'db> {
780767
visibility_constraints: self.visibility_constraints.build(),
781768
bindings_by_use: self.bindings_by_use,
782769
public_symbols: self.symbol_states,
783-
definitions_by_definition: self.definitions_by_definition,
770+
declarations_by_binding: self.declarations_by_binding,
771+
bindings_by_declaration: self.bindings_by_declaration,
784772
eager_bindings: self.eager_bindings,
785773
}
786774
}

crates/red_knot_python_semantic/src/semantic_index/use_def/symbol_state.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ type VisibilityConstraintsIterator<'a> = std::slice::Iter<'a, ScopedVisibilityCo
112112

113113
/// Live declarations for a single symbol at some point in control flow, with their
114114
/// corresponding visibility constraints.
115-
#[derive(Clone, Debug, Default, PartialEq, Eq)]
115+
#[derive(Clone, Debug, Default, PartialEq, Eq, salsa::Update)]
116116
pub(super) struct SymbolDeclarations {
117117
/// [`BitSet`]: which declarations (as [`ScopedDefinitionId`]) can reach the current location?
118118
///
@@ -200,7 +200,7 @@ impl SymbolDeclarations {
200200

201201
/// Live bindings for a single symbol at some point in control flow. Each live binding comes
202202
/// with a set of narrowing constraints and a visibility constraint.
203-
#[derive(Clone, Debug, Default, PartialEq, Eq)]
203+
#[derive(Clone, Debug, Default, PartialEq, Eq, salsa::Update)]
204204
pub(super) struct SymbolBindings {
205205
/// [`BitSet`]: which bindings (as [`ScopedDefinitionId`]) can reach the current location?
206206
///

crates/red_knot_python_semantic/src/symbol.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ fn core_module_scope(db: &dyn Db, core_module: KnownModule) -> Option<ScopeId<'_
293293
/// together with boundness information in a [`Symbol`].
294294
///
295295
/// The type will be a union if there are multiple bindings with different types.
296-
pub(crate) fn symbol_from_bindings<'db>(
296+
pub(super) fn symbol_from_bindings<'db>(
297297
db: &'db dyn Db,
298298
bindings_with_constraints: BindingWithConstraintsIterator<'_, 'db>,
299299
) -> Symbol<'db> {
@@ -479,6 +479,10 @@ fn symbol_impl<'db>(
479479
}
480480

481481
/// Implementation of [`symbol_from_bindings`].
482+
///
483+
/// ## Implementation Note
484+
/// This function gets called cross-module. It, therefore, shouldn't
485+
/// access any AST nodes from the file containing the declarations.
482486
fn symbol_from_bindings_impl<'db>(
483487
db: &'db dyn Db,
484488
bindings_with_constraints: BindingWithConstraintsIterator<'_, 'db>,
@@ -564,6 +568,10 @@ fn symbol_from_bindings_impl<'db>(
564568
}
565569

566570
/// Implementation of [`symbol_from_declarations`].
571+
///
572+
/// ## Implementation Note
573+
/// This function gets called cross-module. It, therefore, shouldn't
574+
/// access any AST nodes from the file containing the declarations.
567575
fn symbol_from_declarations_impl<'db>(
568576
db: &'db dyn Db,
569577
declarations: DeclarationsIterator<'_, 'db>,

crates/red_knot_python_semantic/src/types.rs

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ pub(crate) use self::diagnostic::register_lints;
1616
pub use self::diagnostic::{TypeCheckDiagnostic, TypeCheckDiagnostics};
1717
pub(crate) use self::display::TypeArrayDisplay;
1818
pub(crate) use self::infer::{
19-
infer_deferred_types, infer_definition_types, infer_expression_types, infer_scope_types,
19+
infer_deferred_types, infer_definition_types, infer_expression_type, infer_expression_types,
20+
infer_scope_types,
2021
};
2122
pub use self::narrow::KnownConstraintFunction;
2223
pub(crate) use self::signatures::Signature;
@@ -26,7 +27,6 @@ use crate::module_resolver::{file_to_module, resolve_module, KnownModule};
2627
use crate::semantic_index::ast_ids::HasScopedExpressionId;
2728
use crate::semantic_index::attribute_assignment::AttributeAssignment;
2829
use crate::semantic_index::definition::Definition;
29-
use crate::semantic_index::expression::Expression;
3030
use crate::semantic_index::symbol::ScopeId;
3131
use crate::semantic_index::{
3232
attribute_assignments, imported_modules, semantic_index, symbol_table, use_def_map,
@@ -3818,16 +3818,6 @@ impl<'db> Class<'db> {
38183818
name: &str,
38193819
inferred_type_from_class_body: Option<Type<'db>>,
38203820
) -> Symbol<'db> {
3821-
// We use a separate salsa query here to prevent unrelated changes in the AST of an external
3822-
// file from triggering re-evaluations of downstream queries.
3823-
// See the `dependency_implicit_instance_attribute` test for more information.
3824-
#[salsa::tracked]
3825-
fn infer_expression_type<'db>(db: &'db dyn Db, expression: Expression<'db>) -> Type<'db> {
3826-
let inference = infer_expression_types(db, expression);
3827-
let expr_scope = expression.scope(db);
3828-
inference.expression_type(expression.node_ref(db).scoped_expression_id(db, expr_scope))
3829-
}
3830-
38313821
// If we do not see any declarations of an attribute, neither in the class body nor in
38323822
// any method, we build a union of `Unknown` with the inferred types of all bindings of
38333823
// that attribute. We include `Unknown` in that union to account for the fact that the

0 commit comments

Comments
 (0)