Skip to content

[mypyc] Produce unimplemented errors on unsupported async features #10595

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 8, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions mypyc/codegen/emitmodule.py
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,10 @@ def compile_modules_to_c(
group_map = {source.module: lib_name for group, lib_name in groups for source in group}
mapper = Mapper(group_map)

# Sometimes when we call back into mypy, there might be errors.
# We don't want to crash when that happens.
result.manager.errors.set_file('<mypyc>', module=None, scope=None)

modules = compile_modules_to_ir(result, mapper, compiler_options, errors)
ctext = compile_ir_to_c(groups, modules, result, mapper, compiler_options)

Expand Down
4 changes: 4 additions & 0 deletions mypyc/irbuild/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ def namespaced_name(self) -> str:
def is_generator(self) -> bool:
return self.fitem.is_generator or self.fitem.is_coroutine

@property
def is_coroutine(self) -> bool:
return self.fitem.is_coroutine

@property
def callable_class(self) -> 'ImplicitClass':
assert self._callable_class is not None
Expand Down
10 changes: 10 additions & 0 deletions mypyc/irbuild/expression.py
Original file line number Diff line number Diff line change
Expand Up @@ -659,14 +659,21 @@ def _visit_display(builder: IRBuilder,


def transform_list_comprehension(builder: IRBuilder, o: ListComprehension) -> Value:
if any(o.generator.is_async):
builder.error('async comprehensions are unimplemented', o.line)
return translate_list_comprehension(builder, o.generator)


def transform_set_comprehension(builder: IRBuilder, o: SetComprehension) -> Value:
if any(o.generator.is_async):
builder.error('async comprehensions are unimplemented', o.line)
return translate_set_comprehension(builder, o.generator)


def transform_dictionary_comprehension(builder: IRBuilder, o: DictionaryComprehension) -> Value:
if any(o.is_async):
builder.error('async comprehensions are unimplemented', o.line)

d = builder.call_c(dict_new_op, [], o.line)
loop_params = list(zip(o.indices, o.sequences, o.condlists))

Expand Down Expand Up @@ -696,6 +703,9 @@ def get_arg(arg: Optional[Expression]) -> Value:


def transform_generator_expr(builder: IRBuilder, o: GeneratorExpr) -> Value:
if any(o.is_async):
builder.error('async comprehensions are unimplemented', o.line)

builder.warning('Treating generator comprehension as list', o.line)
return builder.call_c(
iter_op, [translate_list_comprehension(builder, o)], o.line
Expand Down
3 changes: 3 additions & 0 deletions mypyc/irbuild/function.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,9 @@ def transform_lambda_expr(builder: IRBuilder, expr: LambdaExpr) -> Value:


def transform_yield_expr(builder: IRBuilder, expr: YieldExpr) -> Value:
if builder.fn_info.is_coroutine:
builder.error('async generators are unimplemented', expr.line)

if expr.expr:
retval = builder.accept(expr.expr)
else:
Expand Down
6 changes: 6 additions & 0 deletions mypyc/irbuild/statement.py
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,9 @@ def transform_while_stmt(builder: IRBuilder, s: WhileStmt) -> None:


def transform_for_stmt(builder: IRBuilder, s: ForStmt) -> None:
if s.is_async:
builder.error('async for is unimplemented', s.line)

def body() -> None:
builder.accept(s.body)

Expand Down Expand Up @@ -610,6 +613,9 @@ def finally_body() -> None:


def transform_with_stmt(builder: IRBuilder, o: WithStmt) -> None:
if o.is_async:
builder.error('async with is unimplemented', o.line)

# Generate separate logic for each expr in it, left to right
def generate(i: int) -> None:
if i >= len(o.expr):
Expand Down
22 changes: 21 additions & 1 deletion mypyc/test-data/commandline.test
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ def f(x: int) -> int:
# cmd: test.py

[file test.py]
from typing import List, Any
from typing import List, Any, AsyncIterable
from typing_extensions import Final
from mypy_extensions import trait, mypyc_attr

Expand Down Expand Up @@ -192,3 +192,23 @@ class AllowInterp1(Concrete1): # E: Base class "test.Concrete1" does not allow
@mypyc_attr(allow_interpreted_subclasses=True)
class AllowInterp2(PureTrait): # E: Base class "test.PureTrait" does not allow interpreted subclasses
pass

async def async_for(xs: AsyncIterable[int]) -> None:
async for x in xs: # E: async for is unimplemented
print(x)

[x async for x in xs] # E: async comprehensions are unimplemented
(x async for x in xs) # E: async comprehensions are unimplemented # W: Treating generator comprehension as list
{x async for x in xs} # E: async comprehensions are unimplemented
{x: x async for x in xs} # E: async comprehensions are unimplemented

class async_ctx:
async def __aenter__(self) -> int: pass
async def __aexit__(self, x, y, z) -> None: pass

async def async_with() -> None:
async with async_ctx() as x: # E: async with is unimplemented
print(x)

async def async_generators() -> AsyncIterable[int]:
yield 1 # E: async generators are unimplemented