mirror of https://github.com/astral-sh/ruff
walk the scopes
This commit is contained in:
parent
5945ca6fce
commit
3782ccf028
|
|
@ -6867,6 +6867,10 @@ impl<'db> FunctionType<'db> {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn non_overloaded_signature(self, db: &'db dyn Db) -> Signature<'db> {
|
||||
self.internal_signature(db, self.inherited_generic_context(db))
|
||||
}
|
||||
|
||||
/// Typed internally-visible signature for this function.
|
||||
///
|
||||
/// This represents the annotations on the function itself, unmodified by decorators and
|
||||
|
|
|
|||
|
|
@ -105,6 +105,15 @@ impl<'db> GenericContext<'db> {
|
|||
Some(Self::new(db, variables, GenericContextOrigin::Inherited))
|
||||
}
|
||||
|
||||
pub(crate) fn is_legacy(self, db: &'db dyn Db) -> bool {
|
||||
matches!(
|
||||
self.origin(db),
|
||||
GenericContextOrigin::LegacyBase(_)
|
||||
| GenericContextOrigin::Inherited
|
||||
| GenericContextOrigin::LegacyGenericFunction
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn len(self, db: &'db dyn Db) -> usize {
|
||||
self.variables(db).len()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -355,6 +355,42 @@ pub(crate) fn enclosing_class_symbol<'db>(
|
|||
})
|
||||
}
|
||||
|
||||
/// Returns in iterator of any generic context introduced by the given scope or any enclosing
|
||||
/// scope.
|
||||
pub(crate) fn enclosing_generic_contexts<'db>(
|
||||
db: &'db dyn Db,
|
||||
index: &SemanticIndex<'db>,
|
||||
scope: ScopeId,
|
||||
) -> impl Iterator<Item = GenericContext<'db>> {
|
||||
index
|
||||
.ancestor_scopes(scope.file_scope_id(db))
|
||||
.filter_map(|(_, ancestor_scope)| match ancestor_scope.node() {
|
||||
NodeWithScopeKind::Class(class) => {
|
||||
binding_type(db, index.expect_single_definition(class.node()))
|
||||
.into_class_literal()?
|
||||
.generic_context(db)
|
||||
}
|
||||
NodeWithScopeKind::Function(function) => {
|
||||
binding_type(db, index.expect_single_definition(function.node()))
|
||||
.into_function_literal()?
|
||||
.non_overloaded_signature(db)
|
||||
.generic_context
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns the legacy typevars that have been bound in the given scope or any enclosing scope.
|
||||
pub(crate) fn bound_legacy_typevars<'db>(
|
||||
db: &'db dyn Db,
|
||||
index: &'db SemanticIndex<'db>,
|
||||
scope: ScopeId,
|
||||
) -> impl Iterator<Item = TypeVarInstance<'db>> {
|
||||
enclosing_generic_contexts(db, index, scope)
|
||||
.filter(|generic_context| generic_context.is_legacy(db))
|
||||
.flat_map(|generic_context| generic_context.variables(db).iter().copied())
|
||||
}
|
||||
|
||||
/// A region within which we can infer types.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub(crate) enum InferenceRegion<'db> {
|
||||
|
|
@ -4233,7 +4269,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
|||
}
|
||||
|
||||
fn infer_expression_impl(&mut self, expression: &ast::Expr) -> Type<'db> {
|
||||
let ty = match expression {
|
||||
let mut ty = match expression {
|
||||
ast::Expr::NoneLiteral(ast::ExprNoneLiteral { range: _ }) => Type::none(self.db()),
|
||||
ast::Expr::NumberLiteral(literal) => self.infer_number_literal_expression(literal),
|
||||
ast::Expr::BooleanLiteral(literal) => self.infer_boolean_literal_expression(literal),
|
||||
|
|
@ -4274,6 +4310,12 @@ impl<'db> TypeInferenceBuilder<'db> {
|
|||
}
|
||||
};
|
||||
|
||||
// If the expression resolves to a legacy typevar, we will have the TypeVarInstance that
|
||||
// was created when the typevar was created, which will not have an associated definition.
|
||||
// Walk the enclosing scopes, looking for the nearest generic context that binds the
|
||||
// typevar.
|
||||
if let Type::TypeVar(typevar) = f
|
||||
|
||||
self.store_expression_type(expression, ty);
|
||||
|
||||
ty
|
||||
|
|
|
|||
Loading…
Reference in New Issue