diff --git a/crates/ty_python_semantic/resources/mdtest/annotations/invalid.md b/crates/ty_python_semantic/resources/mdtest/annotations/invalid.md index 9dca3893b7..29542eb8d5 100644 --- a/crates/ty_python_semantic/resources/mdtest/annotations/invalid.md +++ b/crates/ty_python_semantic/resources/mdtest/annotations/invalid.md @@ -56,6 +56,7 @@ def _( def bar() -> None: return None +async def baz(): ... async def outer(): # avoid unrelated syntax errors on yield, yield from, and await def _( a: 1, # error: [invalid-type-form] "Int literals are not allowed in this context in a type expression" @@ -69,7 +70,7 @@ async def outer(): # avoid unrelated syntax errors on yield, yield from, and aw i: not 1, # error: [invalid-type-form] "Unary operations are not allowed in type expressions" j: lambda: 1, # error: [invalid-type-form] "`lambda` expressions are not allowed in type expressions" k: 1 if True else 2, # error: [invalid-type-form] "`if` expressions are not allowed in type expressions" - l: await 1, # error: [invalid-type-form] "`await` expressions are not allowed in type expressions" + l: await baz(), # error: [invalid-type-form] "`await` expressions are not allowed in type expressions" m: (yield 1), # error: [invalid-type-form] "`yield` expressions are not allowed in type expressions" n: (yield from [1]), # error: [invalid-type-form] "`yield from` expressions are not allowed in type expressions" o: 1 < 2, # error: [invalid-type-form] "Comparison expressions are not allowed in type expressions" diff --git a/crates/ty_python_semantic/resources/mdtest/diagnostics/semantic_syntax_errors.md b/crates/ty_python_semantic/resources/mdtest/diagnostics/semantic_syntax_errors.md index 84e4f362bb..5e77445b07 100644 --- a/crates/ty_python_semantic/resources/mdtest/diagnostics/semantic_syntax_errors.md +++ b/crates/ty_python_semantic/resources/mdtest/diagnostics/semantic_syntax_errors.md @@ -124,6 +124,9 @@ match obj: ## `return`, `yield`, `yield from`, and `await` outside function ```py +class C: + def __await__(self): ... + # error: [invalid-syntax] "`return` statement outside of a function" return @@ -135,11 +138,11 @@ yield from [] # error: [invalid-syntax] "`await` statement outside of a function" # error: [invalid-syntax] "`await` outside of an asynchronous function" -await 1 +await C() def f(): # error: [invalid-syntax] "`await` outside of an asynchronous function" - await 1 + await C() ``` Generators are evaluated lazily, so `await` is allowed, even outside of a function. @@ -330,7 +333,8 @@ async def elements(n): def _(): # error: [invalid-syntax] "`await` outside of an asynchronous function" - await 1 + await elements(1) + # error: [invalid-syntax] "`async for` outside of an asynchronous function" async for _ in elements(1): ... diff --git a/crates/ty_python_semantic/resources/mdtest/scopes/unbound.md b/crates/ty_python_semantic/resources/mdtest/scopes/unbound.md index 8185db8f0d..8729012093 100644 --- a/crates/ty_python_semantic/resources/mdtest/scopes/unbound.md +++ b/crates/ty_python_semantic/resources/mdtest/scopes/unbound.md @@ -40,6 +40,22 @@ class C: reveal_type(C.y) # revealed: Unknown | Literal[1, "abc"] ``` +## Possibly unbound in class scope with multiple declarations + +```py +def coinflip() -> bool: + return True + +class C: + if coinflip(): + x: int = 1 + elif coinflip(): + x: str = "abc" + +# error: [possibly-unbound-attribute] +reveal_type(C.x) # revealed: int | str +``` + ## Unbound function local An unbound function local that has definitions in the scope does not fall back to globals. diff --git a/crates/ty_python_semantic/src/place.rs b/crates/ty_python_semantic/src/place.rs index de0c95b427..41fc651dc1 100644 --- a/crates/ty_python_semantic/src/place.rs +++ b/crates/ty_python_semantic/src/place.rs @@ -472,12 +472,56 @@ pub(crate) fn place_from_declarations<'db>( place_from_declarations_impl(db, declarations, RequiresExplicitReExport::No) } -pub(crate) type DeclaredTypeAndConflictingTypes<'db> = - (TypeAndQualifiers<'db>, Box>>); +type DeclaredTypeAndConflictingTypes<'db> = ( + TypeAndQualifiers<'db>, + Option>>>, +); /// The result of looking up a declared type from declarations; see [`place_from_declarations`]. -pub(crate) type PlaceFromDeclarationsResult<'db> = - Result, DeclaredTypeAndConflictingTypes<'db>>; +pub(crate) struct PlaceFromDeclarationsResult<'db> { + place_and_quals: PlaceAndQualifiers<'db>, + conflicting_types: Option>>>, +} + +impl<'db> PlaceFromDeclarationsResult<'db> { + fn conflict( + place_and_quals: PlaceAndQualifiers<'db>, + conflicting_types: Box>>, + ) -> Self { + PlaceFromDeclarationsResult { + place_and_quals, + conflicting_types: Some(conflicting_types), + } + } + + pub(crate) fn ignore_conflicting_declarations(self) -> PlaceAndQualifiers<'db> { + self.place_and_quals + } + + pub(crate) fn into_place_and_conflicting_declarations( + self, + ) -> ( + PlaceAndQualifiers<'db>, + Option>>>, + ) { + (self.place_and_quals, self.conflicting_types) + } +} + +impl<'db> From> for PlaceFromDeclarationsResult<'db> { + fn from(place_and_quals: PlaceAndQualifiers<'db>) -> Self { + PlaceFromDeclarationsResult { + place_and_quals, + conflicting_types: None, + } + } +} + +impl<'db> From> for PlaceFromDeclarationsResult<'db> { + fn from(place: Place<'db>) -> Self { + PlaceFromDeclarationsResult::from(PlaceAndQualifiers::from(place)) + } +} /// A type with declaredness information, and a set of type qualifiers. /// @@ -659,7 +703,8 @@ fn place_by_id<'db>( ConsideredDefinitions::AllReachable => use_def.all_reachable_declarations(place_id), }; - let declared = place_from_declarations_impl(db, declarations, requires_explicit_reexport); + let declared = place_from_declarations_impl(db, declarations, requires_explicit_reexport) + .ignore_conflicting_declarations(); let all_considered_bindings = || match considered_definitions { ConsideredDefinitions::EndOfScope => use_def.end_of_scope_bindings(place_id), @@ -668,53 +713,41 @@ fn place_by_id<'db>( // If a symbol is undeclared, but qualified with `typing.Final`, we use the right-hand side // inferred type, without unioning with `Unknown`, because it can not be modified. - if let Some(qualifiers) = declared - .as_ref() - .ok() - .and_then(PlaceAndQualifiers::is_bare_final) - { + if let Some(qualifiers) = declared.is_bare_final() { let bindings = all_considered_bindings(); return place_from_bindings_impl(db, bindings, requires_explicit_reexport) .with_qualifiers(qualifiers); } - // Handle bare `ClassVar` annotations by falling back to the union of `Unknown` and the - // inferred type. match declared { - Ok(PlaceAndQualifiers { + // Handle bare `ClassVar` annotations by falling back to the union of `Unknown` and the + // inferred type. + PlaceAndQualifiers { place: Place::Type(Type::Dynamic(DynamicType::Unknown), declaredness), qualifiers, - }) if qualifiers.contains(TypeQualifiers::CLASS_VAR) => { + } if qualifiers.contains(TypeQualifiers::CLASS_VAR) => { let bindings = all_considered_bindings(); match place_from_bindings_impl(db, bindings, requires_explicit_reexport) { - Place::Type(inferred, boundness) => { - return Place::Type( - UnionType::from_elements(db, [Type::unknown(), inferred]), - boundness, - ) - .with_qualifiers(qualifiers); - } + Place::Type(inferred, boundness) => Place::Type( + UnionType::from_elements(db, [Type::unknown(), inferred]), + boundness, + ) + .with_qualifiers(qualifiers), Place::Unbound => { - return Place::Type(Type::unknown(), declaredness).with_qualifiers(qualifiers); + Place::Type(Type::unknown(), declaredness).with_qualifiers(qualifiers) } } } - _ => {} - } - - match declared { // Place is declared, trust the declared type - Ok( - place_and_quals @ PlaceAndQualifiers { - place: Place::Type(_, Boundness::Bound), - qualifiers: _, - }, - ) => place_and_quals, + place_and_quals @ PlaceAndQualifiers { + place: Place::Type(_, Boundness::Bound), + qualifiers: _, + } => place_and_quals, // Place is possibly declared - Ok(PlaceAndQualifiers { + PlaceAndQualifiers { place: Place::Type(declared_ty, Boundness::PossiblyUnbound), qualifiers, - }) => { + } => { let bindings = all_considered_bindings(); let boundness_analysis = bindings.boundness_analysis; let inferred = place_from_bindings_impl(db, bindings, requires_explicit_reexport); @@ -741,10 +774,10 @@ fn place_by_id<'db>( PlaceAndQualifiers { place, qualifiers } } // Place is undeclared, return the union of `Unknown` with the inferred type - Ok(PlaceAndQualifiers { + PlaceAndQualifiers { place: Place::Unbound, qualifiers: _, - }) => { + } => { let bindings = all_considered_bindings(); let boundness_analysis = bindings.boundness_analysis; let mut inferred = place_from_bindings_impl(db, bindings, requires_explicit_reexport); @@ -786,12 +819,6 @@ fn place_by_id<'db>( .into() } } - // Place has conflicting declared types - Err((declared, _)) => { - // Intentionally ignore conflicting declared types; that's not our problem, - // it's the problem of the module we are importing from. - Place::bound(declared.inner_type()).with_qualifiers(declared.qualifiers()) - } } // TODO (ticket: https://github.com/astral-sh/ruff/issues/14297) Our handling of boundness @@ -1129,18 +1156,20 @@ impl<'db> DeclaredTypeBuilder<'db> { } fn build(mut self) -> DeclaredTypeAndConflictingTypes<'db> { - if !self.conflicting_types.is_empty() { + let type_and_quals = TypeAndQualifiers::new(self.inner.build(), self.qualifiers); + if self.conflicting_types.is_empty() { + (type_and_quals, None) + } else { self.conflicting_types.insert_before( 0, self.first_type .expect("there must be a first type if there are conflicting types"), ); + ( + type_and_quals, + Some(self.conflicting_types.into_boxed_slice()), + ) } - - ( - TypeAndQualifiers::new(self.inner.build(), self.qualifiers), - self.conflicting_types.into_boxed_slice(), - ) } } @@ -1203,22 +1232,16 @@ fn place_from_declarations_impl<'db>( ); if let Some(first) = types.next() { - let declared = if let Some(second) = types.next() { + let (declared, conflicting) = if let Some(second) = types.next() { let mut builder = DeclaredTypeBuilder::new(db); builder.add(first); builder.add(second); for element in types { builder.add(element); } - let (union, conflicting) = builder.build(); - - if !conflicting.is_empty() { - return Err((union, conflicting)); - } - - union + builder.build() } else { - first + (first, None) }; let boundness = match boundness_analysis { @@ -1244,9 +1267,16 @@ fn place_from_declarations_impl<'db>( }, }; - Ok(Place::Type(declared.inner_type(), boundness).with_qualifiers(declared.qualifiers())) + let place_and_quals = + Place::Type(declared.inner_type(), boundness).with_qualifiers(declared.qualifiers()); + + if let Some(conflicting) = conflicting { + PlaceFromDeclarationsResult::conflict(place_and_quals, conflicting) + } else { + place_and_quals.into() + } } else { - Ok(Place::Unbound.into()) + Place::Unbound.into() } } @@ -1281,31 +1311,32 @@ mod implicit_globals { use crate::semantic_index::{place_table, use_def_map}; use crate::types::{KnownClass, Type}; - use super::{Place, PlaceFromDeclarationsResult, place_from_declarations}; + use super::{Place, place_from_declarations}; pub(crate) fn module_type_implicit_global_declaration<'db>( db: &'db dyn Db, name: &str, - ) -> PlaceFromDeclarationsResult<'db> { + ) -> PlaceAndQualifiers<'db> { if !module_type_symbols(db) .iter() .any(|module_type_member| module_type_member == name) { - return Ok(Place::Unbound.into()); + return Place::Unbound.into(); } let Type::ClassLiteral(module_type_class) = KnownClass::ModuleType.to_class_literal(db) else { - return Ok(Place::Unbound.into()); + return Place::Unbound.into(); }; let module_type_scope = module_type_class.body_scope(db); let place_table = place_table(db, module_type_scope); let Some(symbol_id) = place_table.symbol_id(name) else { - return Ok(Place::Unbound.into()); + return Place::Unbound.into(); }; place_from_declarations( db, use_def_map(db, module_type_scope).end_of_scope_symbol_declarations(symbol_id), ) + .ignore_conflicting_declarations() } /// Looks up the type of an "implicit global symbol". Returns [`Place::Unbound`] if diff --git a/crates/ty_python_semantic/src/types/class.rs b/crates/ty_python_semantic/src/types/class.rs index b680cad155..f238ec359b 100644 --- a/crates/ty_python_semantic/src/types/class.rs +++ b/crates/ty_python_semantic/src/types/class.rs @@ -2275,35 +2275,33 @@ impl<'db> ClassLiteral<'db> { let symbol = table.symbol(symbol_id); - if let Ok(attr) = place_from_declarations(db, declarations) { - if attr.is_class_var() { - continue; + let attr = place_from_declarations(db, declarations).ignore_conflicting_declarations(); + if attr.is_class_var() { + continue; + } + + if let Some(attr_ty) = attr.place.ignore_possibly_unbound() { + let bindings = use_def.end_of_scope_symbol_bindings(symbol_id); + let mut default_ty = place_from_bindings(db, bindings).ignore_possibly_unbound(); + + default_ty = + default_ty.map(|ty| ty.apply_optional_specialization(db, specialization)); + + let mut init = true; + if let Some(Type::KnownInstance(KnownInstanceType::Field(field))) = default_ty { + default_ty = Some(field.default_type(db)); + init = field.init(db); } - if let Some(attr_ty) = attr.place.ignore_possibly_unbound() { - let bindings = use_def.end_of_scope_symbol_bindings(symbol_id); - let mut default_ty = - place_from_bindings(db, bindings).ignore_possibly_unbound(); - - default_ty = - default_ty.map(|ty| ty.apply_optional_specialization(db, specialization)); - - let mut init = true; - if let Some(Type::KnownInstance(KnownInstanceType::Field(field))) = default_ty { - default_ty = Some(field.default_type(db)); - init = field.init(db); - } - - attributes.insert( - symbol.name().clone(), - Field { - declared_ty: attr_ty.apply_optional_specialization(db, specialization), - default_ty, - init_only: attr.is_init_var(), - init, - }, - ); - } + attributes.insert( + symbol.name().clone(), + Field { + declared_ty: attr_ty.apply_optional_specialization(db, specialization), + default_ty, + init_only: attr.is_init_var(), + init, + }, + ); } } @@ -2735,13 +2733,14 @@ impl<'db> ClassLiteral<'db> { let use_def = use_def_map(db, body_scope); let declarations = use_def.end_of_scope_symbol_declarations(symbol_id); - let declared_and_qualifiers = place_from_declarations(db, declarations); + let declared_and_qualifiers = + place_from_declarations(db, declarations).ignore_conflicting_declarations(); match declared_and_qualifiers { - Ok(PlaceAndQualifiers { + PlaceAndQualifiers { place: mut declared @ Place::Type(declared_ty, declaredness), qualifiers, - }) => { + } => { // For the purpose of finding instance attributes, ignore `ClassVar` // declarations: if qualifiers.contains(TypeQualifiers::CLASS_VAR) { @@ -2825,19 +2824,15 @@ impl<'db> ClassLiteral<'db> { } } - Ok(PlaceAndQualifiers { + PlaceAndQualifiers { place: Place::Unbound, qualifiers: _, - }) => { + } => { // The attribute is not *declared* in the class body. It could still be declared/bound // in a method. Self::implicit_attribute(db, body_scope, name, MethodDecorator::None) } - Err((declared, _conflicting_declarations)) => { - // There are conflicting declarations for this attribute in the class body. - Place::bound(declared.inner_type()).with_qualifiers(declared.qualifiers()) - } } } else { // This attribute is neither declared nor bound in the class body. diff --git a/crates/ty_python_semantic/src/types/enums.rs b/crates/ty_python_semantic/src/types/enums.rs index 31c2e1fddf..fb6f5b0c33 100644 --- a/crates/ty_python_semantic/src/types/enums.rs +++ b/crates/ty_python_semantic/src/types/enums.rs @@ -191,23 +191,24 @@ pub(crate) fn enum_metadata<'db>( } let declarations = use_def_map.end_of_scope_symbol_declarations(symbol_id); - let declared = place_from_declarations(db, declarations); + let declared = + place_from_declarations(db, declarations).ignore_conflicting_declarations(); match declared { - Ok(PlaceAndQualifiers { + PlaceAndQualifiers { place: Place::Type(Type::Dynamic(DynamicType::Unknown), _), qualifiers, - }) if qualifiers.contains(TypeQualifiers::FINAL) => {} - Ok(PlaceAndQualifiers { + } if qualifiers.contains(TypeQualifiers::FINAL) => {} + PlaceAndQualifiers { place: Place::Unbound, .. - }) => { + } => { // Undeclared attributes are considered members } - Ok(PlaceAndQualifiers { + PlaceAndQualifiers { place: Place::Type(Type::NominalInstance(instance), _), .. - }) if instance.class(db).is_known(db, KnownClass::Member) => { + } if instance.class(db).is_known(db, KnownClass::Member) => { // If the attribute is specifically declared with `enum.member`, it is considered a member } _ => { diff --git a/crates/ty_python_semantic/src/types/ide_support.rs b/crates/ty_python_semantic/src/types/ide_support.rs index 39262c8b33..8c54ef921a 100644 --- a/crates/ty_python_semantic/src/types/ide_support.rs +++ b/crates/ty_python_semantic/src/types/ide_support.rs @@ -35,15 +35,15 @@ pub(crate) fn all_declarations_and_bindings<'db>( .all_end_of_scope_symbol_declarations() .filter_map(move |(symbol_id, declarations)| { place_from_declarations(db, declarations) - .ok() - .and_then(|result| { - result.place.ignore_possibly_unbound().map(|ty| { - let symbol = table.symbol(symbol_id); - Member { - name: symbol.name().clone(), - ty, - } - }) + .ignore_conflicting_declarations() + .place + .ignore_possibly_unbound() + .map(|ty| { + let symbol = table.symbol(symbol_id); + Member { + name: symbol.name().clone(), + ty, + } }) }) .chain(use_def_map.all_end_of_scope_symbol_bindings().filter_map( diff --git a/crates/ty_python_semantic/src/types/infer.rs b/crates/ty_python_semantic/src/types/infer.rs index 48312e374c..f8bf887e0f 100644 --- a/crates/ty_python_semantic/src/types/infer.rs +++ b/crates/ty_python_semantic/src/types/infer.rs @@ -1921,85 +1921,75 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> { (use_def.declarations_at_binding(binding), true) }; - let (declared_ty, is_modifiable) = place_from_declarations(self.db(), declarations) - .and_then(|place_and_quals| { - Ok( - if matches!(place_and_quals.place, Place::Type(_, Boundness::Bound)) { - place_and_quals - } else if let PlaceExprRef::Symbol(symbol) = place { - let symbol_id = place_id.expect_symbol(); + let (mut place_and_quals, conflicting) = place_from_declarations(self.db(), declarations) + .into_place_and_conflicting_declarations(); - if self.skip_non_global_scopes(file_scope_id, symbol_id) - || self.scope.file_scope_id(self.db()).is_global() - { - let module_type_declarations = - module_type_implicit_global_declaration(self.db(), symbol.name())?; - place_and_quals.or_fall_back_to(self.db(), || module_type_declarations) - } else { - place_and_quals - } - } else { - place_and_quals - }, - ) - }) - .map( - |PlaceAndQualifiers { - place: resolved_place, - qualifiers, - }| { - let is_modifiable = !qualifiers.contains(TypeQualifiers::FINAL); + if let Some(conflicting) = conflicting { + // TODO point out the conflicting declarations in the diagnostic? + let place = place_table.place(binding.place(db)); + if let Some(builder) = self.context.report_lint(&CONFLICTING_DECLARATIONS, node) { + builder.into_diagnostic(format_args!( + "Conflicting declared types for `{place}`: {}", + format_enumeration(conflicting.iter().map(|ty| ty.display(db))) + )); + } + } - if resolved_place.is_unbound() && !place_table.place(place_id).is_symbol() { - if let AnyNodeRef::ExprAttribute(ast::ExprAttribute { - value, attr, .. - }) = node - { - let value_type = self.infer_maybe_standalone_expression(value); - if let Place::Type(ty, Boundness::Bound) = - value_type.member(db, attr).place - { - // TODO: also consider qualifiers on the attribute - return (ty, is_modifiable); - } - } else if let AnyNodeRef::ExprSubscript( - subscript @ ast::ExprSubscript { - value, slice, ctx, .. - }, - ) = node - { - let value_ty = self.infer_expression(value); - let slice_ty = self.infer_expression(slice); - let result_ty = self.infer_subscript_expression_types( - subscript, value_ty, slice_ty, *ctx, - ); - return (result_ty, is_modifiable); - } - } - ( - resolved_place - .ignore_possibly_unbound() - .unwrap_or(Type::unknown()), - is_modifiable, - ) - }, - ) - .unwrap_or_else(|(ty, conflicting)| { - // TODO point out the conflicting declarations in the diagnostic? - let place = place_table.place(binding.place(db)); - if let Some(builder) = self.context.report_lint(&CONFLICTING_DECLARATIONS, node) { - builder.into_diagnostic(format_args!( - "Conflicting declared types for `{place}`: {}", - format_enumeration(conflicting.iter().map(|ty| ty.display(db))) - )); + // Fall back to implicit module globals for (possibly) unbound names + if !matches!(place_and_quals.place, Place::Type(_, Boundness::Bound)) { + if let PlaceExprRef::Symbol(symbol) = place { + let symbol_id = place_id.expect_symbol(); + + if self.skip_non_global_scopes(file_scope_id, symbol_id) + || self.scope.file_scope_id(self.db()).is_global() + { + place_and_quals = place_and_quals.or_fall_back_to(self.db(), || { + module_type_implicit_global_declaration(self.db(), symbol.name()) + }); } - ( - ty.inner_type(), - !ty.qualifiers.contains(TypeQualifiers::FINAL), - ) - }); + } + } - if !is_modifiable { + let PlaceAndQualifiers { + place: resolved_place, + qualifiers, + } = place_and_quals; + + let unwrap_declared_ty = || { + resolved_place + .ignore_possibly_unbound() + .unwrap_or(Type::unknown()) + }; + + // If the place is unbound and its an attribute or subscript place, fall back to normal + // attribute/subscript inference on the root type. + let declared_ty = if resolved_place.is_unbound() && !place_table.place(place_id).is_symbol() + { + if let AnyNodeRef::ExprAttribute(ast::ExprAttribute { value, attr, .. }) = node { + let value_type = self.infer_maybe_standalone_expression(value); + if let Place::Type(ty, Boundness::Bound) = value_type.member(db, attr).place { + // TODO: also consider qualifiers on the attribute + ty + } else { + unwrap_declared_ty() + } + } else if let AnyNodeRef::ExprSubscript( + subscript @ ast::ExprSubscript { + value, slice, ctx, .. + }, + ) = node + { + let value_ty = self.infer_expression(value); + let slice_ty = self.infer_expression(slice); + self.infer_subscript_expression_types(subscript, value_ty, slice_ty, *ctx) + } else { + unwrap_declared_ty() + } + } else { + unwrap_declared_ty() + }; + + if qualifiers.contains(TypeQualifiers::FINAL) { let mut previous_bindings = use_def.bindings_at_definition(binding); // An assignment to a local `Final`-qualified symbol is only an error if there are prior bindings diff --git a/crates/ty_python_semantic/src/types/protocol_class.rs b/crates/ty_python_semantic/src/types/protocol_class.rs index eab39163fd..b129a8800f 100644 --- a/crates/ty_python_semantic/src/types/protocol_class.rs +++ b/crates/ty_python_semantic/src/types/protocol_class.rs @@ -538,8 +538,11 @@ fn cached_protocol_interface<'db>( members.extend( use_def_map .all_end_of_scope_symbol_declarations() - .flat_map(|(symbol_id, declarations)| { - place_from_declarations(db, declarations).map(|place| (symbol_id, place)) + .map(|(symbol_id, declarations)| { + ( + symbol_id, + place_from_declarations(db, declarations).ignore_conflicting_declarations(), + ) }) .filter_map(|(symbol_id, place)| { place diff --git a/python/py-fuzzer/fuzz.py b/python/py-fuzzer/fuzz.py index 7735bef15c..1c49702c98 100644 --- a/python/py-fuzzer/fuzz.py +++ b/python/py-fuzzer/fuzz.py @@ -153,7 +153,7 @@ class FuzzResult: def fuzz_code(seed: Seed, args: ResolvedCliArgs) -> FuzzResult: """Return a `FuzzResult` instance describing the fuzzing result from this seed.""" # TODO(carljm) remove once we debug the slowness of these seeds - skip_check = seed in {120, 160, 335} + skip_check = seed in {120, 160, 314, 335} code = generate_random_code(seed) bug_found = False