Compare commits
3 Commits
0.13.3
...
david/no-u
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9452f2c7f6 | ||
|
|
99ebf3746c | ||
|
|
0aa4b9cf78 |
@@ -237,11 +237,11 @@ b: SomeUnknownName = 1 # error: [unresolved-reference]
|
||||
```py
|
||||
from mod import a, b
|
||||
|
||||
reveal_type(a) # revealed: Unknown | Literal[1]
|
||||
reveal_type(a) # revealed: int
|
||||
reveal_type(b) # revealed: Unknown
|
||||
|
||||
# All external modifications of `a` are allowed:
|
||||
a = None
|
||||
a = None # error: [invalid-assignment]
|
||||
```
|
||||
|
||||
### Undeclared and possibly unbound
|
||||
@@ -265,11 +265,11 @@ if flag:
|
||||
# on top of this document.
|
||||
from mod import a, b
|
||||
|
||||
reveal_type(a) # revealed: Unknown | Literal[1]
|
||||
reveal_type(a) # revealed: int
|
||||
reveal_type(b) # revealed: Unknown
|
||||
|
||||
# All external modifications of `a` are allowed:
|
||||
a = None
|
||||
a = None # error: [invalid-assignment]
|
||||
```
|
||||
|
||||
### Undeclared and unbound
|
||||
|
||||
@@ -108,7 +108,7 @@ def foo():
|
||||
global x
|
||||
def bar():
|
||||
# allowed, refers to `x` in the global scope
|
||||
reveal_type(x) # revealed: Unknown | Literal[1]
|
||||
reveal_type(x) # revealed: int
|
||||
bar()
|
||||
del x # allowed, deletes `x` in the global scope (though we don't track that)
|
||||
```
|
||||
|
||||
@@ -25,8 +25,8 @@ reveal_type(y)
|
||||
# error: [possibly-missing-import] "Member `y` of module `maybe_unbound` may be missing"
|
||||
from maybe_unbound import x, y
|
||||
|
||||
reveal_type(x) # revealed: Unknown | Literal[3]
|
||||
reveal_type(y) # revealed: Unknown | Literal[3]
|
||||
reveal_type(x) # revealed: int
|
||||
reveal_type(y) # revealed: int
|
||||
```
|
||||
|
||||
## Maybe unbound annotated
|
||||
@@ -56,7 +56,7 @@ Importing an annotated name prefers the declared type over the inferred type:
|
||||
# error: [possibly-missing-import] "Member `y` of module `maybe_unbound_annotated` may be missing"
|
||||
from maybe_unbound_annotated import x, y
|
||||
|
||||
reveal_type(x) # revealed: Unknown | Literal[3]
|
||||
reveal_type(x) # revealed: int
|
||||
reveal_type(y) # revealed: int
|
||||
```
|
||||
|
||||
|
||||
@@ -784,7 +784,7 @@ class A: ...
|
||||
from subexporter import *
|
||||
|
||||
# TODO: Should we avoid including `Unknown` for this case?
|
||||
reveal_type(__all__) # revealed: Unknown | list[Unknown | str]
|
||||
reveal_type(__all__) # revealed: list[Unknown | str]
|
||||
|
||||
__all__.append("B")
|
||||
|
||||
|
||||
@@ -40,10 +40,10 @@ def __getattr__(name: str) -> int:
|
||||
import mixed_module
|
||||
|
||||
# Explicit attribute should take precedence
|
||||
reveal_type(mixed_module.explicit_attr) # revealed: Unknown | Literal["explicit"]
|
||||
reveal_type(mixed_module.explicit_attr) # revealed: str
|
||||
|
||||
# `__getattr__` should handle unknown attributes
|
||||
reveal_type(mixed_module.dynamic_attr) # revealed: str
|
||||
reveal_type(mixed_module.dynamic_attr) # revealed: int
|
||||
```
|
||||
|
||||
`mixed_module.py`:
|
||||
@@ -51,8 +51,8 @@ reveal_type(mixed_module.dynamic_attr) # revealed: str
|
||||
```py
|
||||
explicit_attr = "explicit"
|
||||
|
||||
def __getattr__(name: str) -> str:
|
||||
return "dynamic"
|
||||
def __getattr__(name: str) -> int:
|
||||
return 1
|
||||
```
|
||||
|
||||
## Precedence: submodules vs `__getattr__`
|
||||
|
||||
@@ -91,19 +91,23 @@ If there's a namespace package with the same name as a module, the module takes
|
||||
`foo.py`:
|
||||
|
||||
```py
|
||||
x = "module"
|
||||
class FromModule: ...
|
||||
|
||||
x = FromModule
|
||||
```
|
||||
|
||||
`foo/bar.py`:
|
||||
|
||||
```py
|
||||
x = "namespace"
|
||||
class FromNamespace: ...
|
||||
|
||||
x = FromNamespace
|
||||
```
|
||||
|
||||
```py
|
||||
from foo import x
|
||||
|
||||
reveal_type(x) # revealed: Unknown | Literal["module"]
|
||||
reveal_type(x) # revealed: <class 'FromModule'>
|
||||
|
||||
import foo.bar # error: [unresolved-import]
|
||||
```
|
||||
|
||||
@@ -144,8 +144,8 @@ X = (Y := 3) + 4
|
||||
```py
|
||||
from exporter import *
|
||||
|
||||
reveal_type(X) # revealed: Unknown | Literal[7]
|
||||
reveal_type(Y) # revealed: Unknown | Literal[3]
|
||||
reveal_type(X) # revealed: int
|
||||
reveal_type(Y) # revealed: int
|
||||
```
|
||||
|
||||
### Global-scope symbols defined in many other ways
|
||||
@@ -781,9 +781,9 @@ else:
|
||||
from exporter import *
|
||||
|
||||
# error: [possibly-unresolved-reference]
|
||||
reveal_type(A) # revealed: Unknown | Literal[1]
|
||||
reveal_type(A) # revealed: int
|
||||
|
||||
reveal_type(B) # revealed: Unknown | Literal[2, 3]
|
||||
reveal_type(B) # revealed: int
|
||||
```
|
||||
|
||||
### Reachability constraints in the importing module
|
||||
@@ -804,7 +804,7 @@ if coinflip():
|
||||
from exporter import *
|
||||
|
||||
# error: [possibly-unresolved-reference]
|
||||
reveal_type(A) # revealed: Unknown | Literal[1]
|
||||
reveal_type(A) # revealed: int
|
||||
```
|
||||
|
||||
### Reachability constraints in the exporting module *and* the importing module
|
||||
|
||||
@@ -95,7 +95,7 @@ TYPE_CHECKING: bool = ...
|
||||
```py
|
||||
from constants import TYPE_CHECKING
|
||||
|
||||
reveal_type(TYPE_CHECKING) # revealed: Literal[True]
|
||||
reveal_type(TYPE_CHECKING) # revealed: bool
|
||||
|
||||
from stub import TYPE_CHECKING
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ class _:
|
||||
[reveal_type(a.z) for _ in range(1)] # revealed: Literal[0]
|
||||
|
||||
def _():
|
||||
reveal_type(a.x) # revealed: Unknown | int | None
|
||||
reveal_type(a.x) # revealed: int | None
|
||||
reveal_type(a.y) # revealed: Unknown | None
|
||||
reveal_type(a.z) # revealed: Unknown | None
|
||||
|
||||
@@ -75,7 +75,7 @@ class _:
|
||||
|
||||
if cond():
|
||||
a = A()
|
||||
reveal_type(a.x) # revealed: int | None | Unknown
|
||||
reveal_type(a.x) # revealed: int | None
|
||||
reveal_type(a.y) # revealed: Unknown | None
|
||||
reveal_type(a.z) # revealed: Unknown | None
|
||||
|
||||
@@ -295,10 +295,10 @@ class C:
|
||||
|
||||
def _():
|
||||
# error: [possibly-missing-attribute]
|
||||
reveal_type(b.a.x[0]) # revealed: Unknown | int | None
|
||||
reveal_type(b.a.x[0]) # revealed: int | None
|
||||
# error: [possibly-missing-attribute]
|
||||
reveal_type(b.a.x) # revealed: Unknown | list[int | None]
|
||||
reveal_type(b.a) # revealed: Unknown | A | None
|
||||
reveal_type(b.a.x) # revealed: list[int | None]
|
||||
reveal_type(b.a) # revealed: A | None
|
||||
```
|
||||
|
||||
## Invalid assignments are not used for narrowing
|
||||
|
||||
@@ -167,11 +167,11 @@ if c.x is not None:
|
||||
|
||||
if c.x is not None:
|
||||
def _():
|
||||
reveal_type(c.x) # revealed: Unknown | int | None
|
||||
reveal_type(c.x) # revealed: int | None
|
||||
|
||||
def _():
|
||||
if c.x is not None:
|
||||
reveal_type(c.x) # revealed: (Unknown & ~None) | int
|
||||
reveal_type(c.x) # revealed: int
|
||||
```
|
||||
|
||||
## Subscript narrowing
|
||||
|
||||
@@ -86,7 +86,7 @@ class B:
|
||||
reveal_type(a.x) # revealed: Literal["a"]
|
||||
|
||||
def f():
|
||||
reveal_type(a.x) # revealed: Unknown | str | None
|
||||
reveal_type(a.x) # revealed: str | None
|
||||
|
||||
[reveal_type(a.x) for _ in range(1)] # revealed: Literal["a"]
|
||||
|
||||
@@ -96,7 +96,7 @@ class C:
|
||||
reveal_type(a.x) # revealed: str | None
|
||||
|
||||
def g():
|
||||
reveal_type(a.x) # revealed: Unknown | str | None
|
||||
reveal_type(a.x) # revealed: str | None
|
||||
|
||||
[reveal_type(a.x) for _ in range(1)] # revealed: str | None
|
||||
|
||||
@@ -109,7 +109,7 @@ class D:
|
||||
reveal_type(a.x) # revealed: Literal["a"]
|
||||
|
||||
def h():
|
||||
reveal_type(a.x) # revealed: Unknown | str | None
|
||||
reveal_type(a.x) # revealed: str | None
|
||||
|
||||
# TODO: should be `str | None`
|
||||
[reveal_type(a.x) for _ in range(1)] # revealed: Literal["a"]
|
||||
@@ -190,7 +190,7 @@ def f(x: str | None):
|
||||
reveal_type(g) # revealed: str
|
||||
|
||||
if a.x is not None:
|
||||
reveal_type(a.x) # revealed: (Unknown & ~None) | str
|
||||
reveal_type(a.x) # revealed: str
|
||||
|
||||
if l[0] is not None:
|
||||
reveal_type(l[0]) # revealed: str
|
||||
@@ -206,7 +206,7 @@ def f(x: str | None):
|
||||
reveal_type(g) # revealed: str
|
||||
|
||||
if a.x is not None:
|
||||
reveal_type(a.x) # revealed: (Unknown & ~None) | str
|
||||
reveal_type(a.x) # revealed: str
|
||||
|
||||
if l[0] is not None:
|
||||
reveal_type(l[0]) # revealed: str
|
||||
@@ -382,12 +382,12 @@ def f():
|
||||
if a.x is not None:
|
||||
def _():
|
||||
# Lazy nested scope narrowing is not performed on attributes/subscripts because it's difficult to track their changes.
|
||||
reveal_type(a.x) # revealed: Unknown | str | None
|
||||
reveal_type(a.x) # revealed: str | None
|
||||
|
||||
class D:
|
||||
reveal_type(a.x) # revealed: (Unknown & ~None) | str
|
||||
reveal_type(a.x) # revealed: str
|
||||
|
||||
[reveal_type(a.x) for _ in range(1)] # revealed: (Unknown & ~None) | str
|
||||
[reveal_type(a.x) for _ in range(1)] # revealed: str
|
||||
|
||||
if l[0] is not None:
|
||||
def _():
|
||||
@@ -473,11 +473,11 @@ def f():
|
||||
if a.x is not None:
|
||||
def _():
|
||||
if a.x != 1:
|
||||
reveal_type(a.x) # revealed: (Unknown & ~Literal[1]) | str | None
|
||||
reveal_type(a.x) # revealed: str | None
|
||||
|
||||
class D:
|
||||
if a.x != 1:
|
||||
reveal_type(a.x) # revealed: (Unknown & ~Literal[1] & ~None) | str
|
||||
reveal_type(a.x) # revealed: str
|
||||
|
||||
if l[0] is not None:
|
||||
def _():
|
||||
|
||||
@@ -263,7 +263,7 @@ if flag():
|
||||
x = 1
|
||||
|
||||
def f() -> None:
|
||||
reveal_type(x) # revealed: Unknown | Literal[1, 2]
|
||||
reveal_type(x) # revealed: int
|
||||
# Function only used inside this branch
|
||||
f()
|
||||
|
||||
|
||||
@@ -29,8 +29,8 @@ if flag():
|
||||
chr: int = 1
|
||||
|
||||
def _():
|
||||
# TODO: Should ideally be `Unknown | Literal[1] | (def abs(x: SupportsAbs[_T], /) -> _T)`
|
||||
reveal_type(abs) # revealed: Unknown | Literal[1]
|
||||
# TODO: Should ideally be `Literal[1] | (def abs(x: SupportsAbs[_T], /) -> _T)`
|
||||
reveal_type(abs) # revealed: int
|
||||
# TODO: Should ideally be `int | (def chr(i: SupportsIndex, /) -> str)`
|
||||
reveal_type(chr) # revealed: int
|
||||
```
|
||||
|
||||
@@ -12,7 +12,7 @@ Function definitions are evaluated lazily.
|
||||
x = 1
|
||||
|
||||
def f():
|
||||
reveal_type(x) # revealed: Unknown | Literal[1, 2]
|
||||
reveal_type(x) # revealed: int
|
||||
|
||||
x = 2
|
||||
```
|
||||
@@ -283,7 +283,7 @@ x = 1
|
||||
|
||||
def _():
|
||||
class C:
|
||||
# revealed: Unknown | Literal[1]
|
||||
# revealed: int
|
||||
[reveal_type(x) for _ in [1]]
|
||||
x = 2
|
||||
```
|
||||
@@ -389,7 +389,7 @@ x = int
|
||||
class C:
|
||||
var: ClassVar[x]
|
||||
|
||||
reveal_type(C.var) # revealed: Unknown | int | str
|
||||
reveal_type(C.var) # revealed: int | str
|
||||
|
||||
x = str
|
||||
```
|
||||
|
||||
@@ -8,7 +8,7 @@ A name reference to a never-defined symbol in a function is implicitly a global
|
||||
x = 1
|
||||
|
||||
def f():
|
||||
reveal_type(x) # revealed: Unknown | Literal[1]
|
||||
reveal_type(x) # revealed: int
|
||||
```
|
||||
|
||||
## Explicit global in function
|
||||
@@ -18,7 +18,7 @@ x = 1
|
||||
|
||||
def f():
|
||||
global x
|
||||
reveal_type(x) # revealed: Unknown | Literal[1]
|
||||
reveal_type(x) # revealed: int
|
||||
```
|
||||
|
||||
## Unassignable type in function
|
||||
@@ -201,7 +201,7 @@ x = 42
|
||||
|
||||
def f():
|
||||
global x
|
||||
reveal_type(x) # revealed: Unknown | Literal[42]
|
||||
reveal_type(x) # revealed: int
|
||||
x = "56"
|
||||
reveal_type(x) # revealed: Literal["56"]
|
||||
```
|
||||
|
||||
@@ -73,10 +73,10 @@ __spec__ = 42 # error: [invalid-assignment] "Object of type `Literal[42]` is no
|
||||
```py
|
||||
import module
|
||||
|
||||
reveal_type(module.__file__) # revealed: Unknown | None
|
||||
reveal_type(module.__file__) # revealed: None
|
||||
reveal_type(module.__path__) # revealed: list[str]
|
||||
reveal_type(module.__doc__) # revealed: Unknown
|
||||
reveal_type(module.__spec__) # revealed: Unknown | ModuleSpec | None
|
||||
reveal_type(module.__spec__) # revealed: ModuleSpec | None
|
||||
# error: [unresolved-attribute]
|
||||
reveal_type(module.__warningregistry__) # revealed: Unknown
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ class C:
|
||||
x = 2
|
||||
|
||||
# error: [possibly-missing-attribute] "Attribute `x` on type `<class 'C'>` may be missing"
|
||||
reveal_type(C.x) # revealed: Unknown | Literal[2]
|
||||
reveal_type(C.x) # revealed: Unknown | int
|
||||
reveal_type(C.y) # revealed: Unknown | Literal[1]
|
||||
```
|
||||
|
||||
@@ -37,7 +37,7 @@ class C:
|
||||
# Possibly unbound variables in enclosing scopes are considered bound.
|
||||
y = x
|
||||
|
||||
reveal_type(C.y) # revealed: Unknown | Literal[1, "abc"]
|
||||
reveal_type(C.y) # revealed: Unknown | Literal[1] | str
|
||||
```
|
||||
|
||||
## Possibly unbound in class scope with multiple declarations
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
spark # too many iterations (in `exported_names` query)
|
||||
steam.py # hangs (single threaded)
|
||||
|
||||
@@ -822,7 +822,11 @@ fn place_by_id<'db>(
|
||||
)
|
||||
});
|
||||
|
||||
if scope.file(db).is_stub(db) || scope.scope(db).visibility().is_private() {
|
||||
if scope.node(db).scope_kind().is_module() {
|
||||
inferred
|
||||
.map_type(|ty| ty.promote_literals(db, false))
|
||||
.into()
|
||||
} else if scope.file(db).is_stub(db) || scope.scope(db).visibility().is_private() {
|
||||
// We generally trust module-level undeclared places in stubs and do not union
|
||||
// with `Unknown`. If we don't do this, simple aliases like `IOError = OSError` in
|
||||
// stubs would result in `IOError` being a union of `OSError` and `Unknown`, which
|
||||
|
||||
@@ -1171,20 +1171,37 @@ impl<'db> Type<'db> {
|
||||
/// Note that this function tries to promote literals to a more user-friendly form than their
|
||||
/// fallback instance type. For example, `def _() -> int` is promoted to `Callable[[], int]`,
|
||||
/// as opposed to `FunctionType`.
|
||||
pub(crate) fn promote_literals(self, db: &'db dyn Db) -> Type<'db> {
|
||||
self.apply_type_mapping(db, &TypeMapping::PromoteLiterals)
|
||||
pub(crate) fn promote_literals(
|
||||
self,
|
||||
db: &'db dyn Db,
|
||||
promote_modules_and_functions: bool,
|
||||
) -> Type<'db> {
|
||||
self.apply_type_mapping(
|
||||
db,
|
||||
&TypeMapping::PromoteLiterals {
|
||||
promote_modules_and_functions,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
/// Like [`Type::promote_literals`], but does not recurse into nested types.
|
||||
fn promote_literals_impl(self, db: &'db dyn Db) -> Type<'db> {
|
||||
fn promote_literals_impl(
|
||||
self,
|
||||
db: &'db dyn Db,
|
||||
promote_modules_and_functions: bool,
|
||||
) -> Type<'db> {
|
||||
match self {
|
||||
Type::StringLiteral(_) | Type::LiteralString => KnownClass::Str.to_instance(db),
|
||||
Type::BooleanLiteral(_) => KnownClass::Bool.to_instance(db),
|
||||
Type::IntLiteral(_) => KnownClass::Int.to_instance(db),
|
||||
Type::BytesLiteral(_) => KnownClass::Bytes.to_instance(db),
|
||||
Type::ModuleLiteral(_) => KnownClass::ModuleType.to_instance(db),
|
||||
Type::EnumLiteral(literal) => literal.enum_class_instance(db),
|
||||
Type::FunctionLiteral(literal) => Type::Callable(literal.into_callable_type(db)),
|
||||
Type::ModuleLiteral(_) if promote_modules_and_functions => {
|
||||
KnownClass::ModuleType.to_instance(db)
|
||||
}
|
||||
Type::FunctionLiteral(literal) if promote_modules_and_functions => {
|
||||
Type::Callable(literal.into_callable_type(db))
|
||||
}
|
||||
_ => self,
|
||||
}
|
||||
}
|
||||
@@ -6037,7 +6054,7 @@ impl<'db> Type<'db> {
|
||||
self
|
||||
}
|
||||
}
|
||||
TypeMapping::PromoteLiterals
|
||||
TypeMapping::PromoteLiterals { .. }
|
||||
| TypeMapping::BindLegacyTypevars(_)
|
||||
| TypeMapping::MarkTypeVarsInferable(_) => self,
|
||||
TypeMapping::Materialize(materialization_kind) => {
|
||||
@@ -6059,7 +6076,7 @@ impl<'db> Type<'db> {
|
||||
self
|
||||
}
|
||||
}
|
||||
TypeMapping::PromoteLiterals
|
||||
TypeMapping::PromoteLiterals { .. }
|
||||
| TypeMapping::BindLegacyTypevars(_)
|
||||
| TypeMapping::BindSelf(_)
|
||||
| TypeMapping::ReplaceSelf { .. }
|
||||
@@ -6074,7 +6091,7 @@ impl<'db> Type<'db> {
|
||||
}
|
||||
TypeMapping::Specialization(_) |
|
||||
TypeMapping::PartialSpecialization(_) |
|
||||
TypeMapping::PromoteLiterals |
|
||||
TypeMapping::PromoteLiterals { .. } |
|
||||
TypeMapping::BindSelf(_) |
|
||||
TypeMapping::ReplaceSelf { .. } |
|
||||
TypeMapping::MarkTypeVarsInferable(_) |
|
||||
@@ -6085,7 +6102,7 @@ impl<'db> Type<'db> {
|
||||
let function = Type::FunctionLiteral(function.apply_type_mapping_impl(db, type_mapping, visitor));
|
||||
|
||||
match type_mapping {
|
||||
TypeMapping::PromoteLiterals => function.promote_literals_impl(db),
|
||||
TypeMapping::PromoteLiterals { promote_modules_and_functions } => function.promote_literals_impl(db, *promote_modules_and_functions),
|
||||
_ => function
|
||||
}
|
||||
}
|
||||
@@ -6193,7 +6210,7 @@ impl<'db> Type<'db> {
|
||||
TypeMapping::ReplaceSelf { .. } |
|
||||
TypeMapping::MarkTypeVarsInferable(_) |
|
||||
TypeMapping::Materialize(_) => self,
|
||||
TypeMapping::PromoteLiterals => self.promote_literals_impl(db)
|
||||
TypeMapping::PromoteLiterals { promote_modules_and_functions } => self.promote_literals_impl(db, *promote_modules_and_functions)
|
||||
}
|
||||
|
||||
Type::Dynamic(_) => match type_mapping {
|
||||
@@ -6203,7 +6220,7 @@ impl<'db> Type<'db> {
|
||||
TypeMapping::BindSelf(_) |
|
||||
TypeMapping::ReplaceSelf { .. } |
|
||||
TypeMapping::MarkTypeVarsInferable(_) |
|
||||
TypeMapping::PromoteLiterals => self,
|
||||
TypeMapping::PromoteLiterals { .. } => self,
|
||||
TypeMapping::Materialize(materialization_kind) => match materialization_kind {
|
||||
MaterializationKind::Top => Type::object(),
|
||||
MaterializationKind::Bottom => Type::Never,
|
||||
@@ -6730,7 +6747,7 @@ pub enum TypeMapping<'a, 'db> {
|
||||
PartialSpecialization(PartialSpecialization<'a, 'db>),
|
||||
/// Replaces any literal types with their corresponding promoted type form (e.g. `Literal["string"]`
|
||||
/// to `str`, or `def _() -> int` to `Callable[[], int]`).
|
||||
PromoteLiterals,
|
||||
PromoteLiterals { promote_modules_and_functions: bool },
|
||||
/// Binds a legacy typevar with the generic context (class, function, type alias) that it is
|
||||
/// being used in.
|
||||
BindLegacyTypevars(BindingContext<'db>),
|
||||
@@ -6763,7 +6780,7 @@ impl<'db> TypeMapping<'_, 'db> {
|
||||
match self {
|
||||
TypeMapping::Specialization(_)
|
||||
| TypeMapping::PartialSpecialization(_)
|
||||
| TypeMapping::PromoteLiterals
|
||||
| TypeMapping::PromoteLiterals { .. }
|
||||
| TypeMapping::BindLegacyTypevars(_)
|
||||
| TypeMapping::MarkTypeVarsInferable(_)
|
||||
| TypeMapping::Materialize(_) => context,
|
||||
|
||||
@@ -2498,9 +2498,12 @@ impl<'a, 'db> ArgumentTypeChecker<'a, 'db> {
|
||||
// The inherited generic context is used when inferring the specialization of a generic
|
||||
// class from a constructor call. In this case (only), we promote any typevars that are
|
||||
// inferred as a literal to the corresponding instance type.
|
||||
builder
|
||||
.build(gc)
|
||||
.apply_type_mapping(self.db, &TypeMapping::PromoteLiterals)
|
||||
builder.build(gc).apply_type_mapping(
|
||||
self.db,
|
||||
&TypeMapping::PromoteLiterals {
|
||||
promote_modules_and_functions: true,
|
||||
},
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -2662,7 +2662,7 @@ pub(crate) fn report_undeclared_protocol_member(
|
||||
if definition.kind(db).is_unannotated_assignment() {
|
||||
let binding_type = binding_type(db, definition);
|
||||
|
||||
let suggestion = binding_type.promote_literals(db);
|
||||
let suggestion = binding_type.promote_literals(db, true);
|
||||
|
||||
if should_give_hint(db, suggestion) {
|
||||
diagnostic.set_primary_message(format_args!(
|
||||
|
||||
@@ -5432,7 +5432,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
||||
|
||||
// Convert any element literals to their promoted type form to avoid excessively large
|
||||
// unions for large nested list literals, which the constraint solver struggles with.
|
||||
let inferred_elt_ty = inferred_elt_ty.promote_literals(self.db());
|
||||
let inferred_elt_ty = inferred_elt_ty.promote_literals(self.db(), true);
|
||||
|
||||
builder
|
||||
.infer(Type::TypeVar(*elt_ty), inferred_elt_ty)
|
||||
|
||||
Reference in New Issue
Block a user