astral-sh/ruff · error
Expected a Type::Dynamic variant
Error message
Expected a Type::Dynamic variant
What it means
Type::expect_dynamic is the unwrapping counterpart of as_dynamic: it asserts a Type value is the Dynamic variant (Any, Unknown, and friends). It fires when a code path that has already reasoned a type must be dynamic actually holds a different variant, i.e., the dynamic-approximation assumption upstream does not hold.
Source
Thrown at crates/ty_python_semantic/src/types.rs:2419
Type::Intersection(intersection) => intersection
.positive(db)
.iter()
.any(|ty| ty.is_awaitable(db)),
_ => false,
}
}
/// Is a value of this type only usable in typing contexts?
pub fn is_type_check_only(&self, db: &'db dyn Db) -> bool {
match self {
Type::ClassLiteral(class_literal) => class_literal.type_check_only(db),
Type::FunctionLiteral(f) => {
f.has_known_decorator(db, FunctionDecorators::TYPE_CHECK_ONLY)
}
_ => false,
}
}
/// Returns whether this type is marked as deprecated via `@warnings.deprecated`.
pub fn is_deprecated(&self, db: &'db dyn Db) -> bool {
match self {
Type::FunctionLiteral(f) => f.implementation_deprecated(db).is_some(),
Type::Callable(callable) => callable.deprecated(db).is_some(),
Type::ClassLiteral(c) => c.deprecated(db).is_some(),
_ => false,
}
}
/// If the type is a specialized instance of the given `KnownClass`, returns the specialization.
fn known_specialization(
&self,
db: &'db dyn Db,
env: &ProgramEnvironment<'db>,
known_class: KnownClass,
) -> Option<Specialization<'db>> {
let class_literal = known_class.try_to_class_literal(db, env)?;View on GitHub (pinned to 15f3fe6b15)
Solutions
- Capture the panic backtrace plus the expression being checked and file a ty issue with a minimal repro
- As a contributor: prefer `let Type::Dynamic(d) = ty else { ... }` or as_dynamic() with an explicit non-dynamic fallback at the call site
- Check whether a newly added Type variant needs handling in the dynamic-approximation helpers
Example fix
// before
let dynamic = ty.expect_dynamic();
// after
if let Some(dynamic) = ty.as_dynamic() {
// dynamic path
} else {
// explicit non-dynamic path
} Defensive patterns
Strategy: type-guard
Type guard
fn is_dynamic<'db>(ty: Type<'db>) -> bool {
matches!(ty, Type::Dynamic(_))
} Prevention
- Prefer as_dynamic()/`if let Type::Dynamic` over expect_dynamic at call sites that can receive other variants
- When adding a Type variant, audit dynamic-approximation helpers and their expect_dynamic call sites
- Cover the non-dynamic path in tests so the assumption is checked rather than assumed
When it happens
Trigger: Calling expect_dynamic on a Type that is not Dynamic - for example after a to_dynamic-style approximation or a match fallback that was expected to produce Any/Unknown but returned another variant, or after a new Type variant is added without updating dynamic-fallback logic.
Common situations: Contributor refactors that replace `if let Type::Dynamic` checks with expect_dynamic; addition of a new Type variant that should participate in dynamic approximations but does not.
Related errors
- The meta-type of an instance-like type should always have an
- matched `Type::Divergent` above
- `find_name_in_mro` should return `Some` for a class literal
- extra use-def data should have been retained
- should be set because `extract_if` only yields elements with
AI-assisted analysis of astral-sh/ruff@15f3fe6b15 (2026-08-20).
Data as JSON: /api/errors/58c6b9ffe73d45b0.
Report an issue: GitHub.