|
159 | 159 | erase_to_bound,
|
160 | 160 | erase_to_union_or_bound,
|
161 | 161 | false_only,
|
| 162 | + fixup_partial_type, |
162 | 163 | function_type,
|
163 | 164 | get_type_vars,
|
164 | 165 | is_literal_type_like,
|
@@ -2738,8 +2739,8 @@ def check_assignment(
|
2738 | 2739 | # None initializers preserve the partial None type.
|
2739 | 2740 | return
|
2740 | 2741 |
|
2741 |
| - if is_valid_inferred_type(rvalue_type): |
2742 |
| - var = lvalue_type.var |
| 2742 | + var = lvalue_type.var |
| 2743 | + if is_valid_inferred_type(rvalue_type, is_lvalue_final=var.is_final): |
2743 | 2744 | partial_types = self.find_partial_types(var)
|
2744 | 2745 | if partial_types is not None:
|
2745 | 2746 | if not self.current_node_deferred:
|
@@ -3687,7 +3688,10 @@ def infer_variable_type(
|
3687 | 3688 | """Infer the type of initialized variables from initializer type."""
|
3688 | 3689 | if isinstance(init_type, DeletedType):
|
3689 | 3690 | self.msg.deleted_as_rvalue(init_type, context)
|
3690 |
| - elif not is_valid_inferred_type(init_type) and not self.no_partial_types: |
| 3691 | + elif ( |
| 3692 | + not is_valid_inferred_type(init_type, is_lvalue_final=name.is_final) |
| 3693 | + and not self.no_partial_types |
| 3694 | + ): |
3691 | 3695 | # We cannot use the type of the initialization expression for full type
|
3692 | 3696 | # inference (it's not specific enough), but we might be able to give
|
3693 | 3697 | # partial type which will be made more specific later. A partial type
|
@@ -6114,7 +6118,7 @@ def enter_partial_types(
|
6114 | 6118 | self.msg.need_annotation_for_var(var, context, self.options.python_version)
|
6115 | 6119 | self.partial_reported.add(var)
|
6116 | 6120 | if var.type:
|
6117 |
| - fixed = self.fixup_partial_type(var.type) |
| 6121 | + fixed = fixup_partial_type(var.type) |
6118 | 6122 | var.invalid_partial_type = fixed != var.type
|
6119 | 6123 | var.type = fixed
|
6120 | 6124 |
|
@@ -6145,20 +6149,7 @@ def handle_partial_var_type(
|
6145 | 6149 | else:
|
6146 | 6150 | # Defer the node -- we might get a better type in the outer scope
|
6147 | 6151 | self.handle_cannot_determine_type(node.name, context)
|
6148 |
| - return self.fixup_partial_type(typ) |
6149 |
| - |
6150 |
| - def fixup_partial_type(self, typ: Type) -> Type: |
6151 |
| - """Convert a partial type that we couldn't resolve into something concrete. |
6152 |
| -
|
6153 |
| - This means, for None we make it Optional[Any], and for anything else we |
6154 |
| - fill in all of the type arguments with Any. |
6155 |
| - """ |
6156 |
| - if not isinstance(typ, PartialType): |
6157 |
| - return typ |
6158 |
| - if typ.type is None: |
6159 |
| - return UnionType.make_union([AnyType(TypeOfAny.unannotated), NoneType()]) |
6160 |
| - else: |
6161 |
| - return Instance(typ.type, [AnyType(TypeOfAny.unannotated)] * len(typ.type.type_vars)) |
| 6152 | + return fixup_partial_type(typ) |
6162 | 6153 |
|
6163 | 6154 | def is_defined_in_base_class(self, var: Var) -> bool:
|
6164 | 6155 | if var.info:
|
@@ -7006,20 +6997,27 @@ def infer_operator_assignment_method(typ: Type, operator: str) -> tuple[bool, st
|
7006 | 6997 | return False, method
|
7007 | 6998 |
|
7008 | 6999 |
|
7009 |
| -def is_valid_inferred_type(typ: Type) -> bool: |
7010 |
| - """Is an inferred type valid? |
| 7000 | +def is_valid_inferred_type(typ: Type, is_lvalue_final: bool = False) -> bool: |
| 7001 | + """Is an inferred type valid and needs no further refinement? |
7011 | 7002 |
|
7012 |
| - Examples of invalid types include the None type or List[<uninhabited>]. |
| 7003 | + Examples of invalid types include the None type (when we are not assigning |
| 7004 | + None to a final lvalue) or List[<uninhabited>]. |
7013 | 7005 |
|
7014 | 7006 | When not doing strict Optional checking, all types containing None are
|
7015 | 7007 | invalid. When doing strict Optional checking, only None and types that are
|
7016 | 7008 | incompletely defined (i.e. contain UninhabitedType) are invalid.
|
7017 | 7009 | """
|
7018 |
| - if isinstance(get_proper_type(typ), (NoneType, UninhabitedType)): |
7019 |
| - # With strict Optional checking, we *may* eventually infer NoneType when |
7020 |
| - # the initializer is None, but we only do that if we can't infer a |
7021 |
| - # specific Optional type. This resolution happens in |
7022 |
| - # leave_partial_types when we pop a partial types scope. |
| 7010 | + proper_type = get_proper_type(typ) |
| 7011 | + if isinstance(proper_type, NoneType): |
| 7012 | + # If the lvalue is final, we may immediately infer NoneType when the |
| 7013 | + # initializer is None. |
| 7014 | + # |
| 7015 | + # If not, we want to defer making this decision. The final inferred |
| 7016 | + # type could either be NoneType or an Optional type, depending on |
| 7017 | + # the context. This resolution happens in leave_partial_types when |
| 7018 | + # we pop a partial types scope. |
| 7019 | + return is_lvalue_final |
| 7020 | + elif isinstance(proper_type, UninhabitedType): |
7023 | 7021 | return False
|
7024 | 7022 | return not typ.accept(NothingSeeker())
|
7025 | 7023 |
|
|
0 commit comments