diff --git a/artiq/compiler/embedding.py b/artiq/compiler/embedding.py index 0d35e63df..943550072 100644 --- a/artiq/compiler/embedding.py +++ b/artiq/compiler/embedding.py @@ -556,24 +556,18 @@ class StitchingInferencer(Inferencer): attr_value_type = builtins.TList(builtins.TInt64()) if attr_value_type is None: - # Slow path. We don't know what exactly is the attribute value, - # so we quote it only for the error message that may possibly result. - ast = self.quote(attr_value, loc) + note = diagnostic.Diagnostic("note", + "while inferring a type for an attribute '{attr}' of a host object", + {"attr": attr_name}, + loc) - def proxy_diagnostic(diag): - note = diagnostic.Diagnostic("note", - "while inferring a type for an attribute '{attr}' of a host object", - {"attr": attr_name}, - loc) - diag.notes.append(note) - - self.engine.process(diag) - - proxy_engine = diagnostic.Engine() - proxy_engine.process = proxy_diagnostic - Inferencer(engine=proxy_engine).visit(ast) - IntMonomorphizer(engine=proxy_engine).visit(ast) - attr_value_type = ast.type + with self.engine.context(note): + # Slow path. We don't know what exactly is the attribute value, + # so we quote it only for the error message that may possibly result. + ast = self.quote(attr_value, object_loc.expanded_from) + Inferencer(engine=self.engine).visit(ast) + IntMonomorphizer(engine=self.engine).visit(ast) + attr_value_type = ast.type return attributes, attr_value_type @@ -840,32 +834,24 @@ class Stitcher: notes=self._call_site_note(loc, is_syscall)) self.engine.process(diag) elif param.default is not inspect.Parameter.empty: - # Try and infer the type from the default value. - # This is tricky, because the default value might not have - # a well-defined type in APython. - # In this case, we bail out, but mention why we do it. - ast = self._quote(param.default, None) + notes = [] + notes.append(diagnostic.Diagnostic("note", + "expanded from here while trying to infer a type for an" + " unannotated optional argument '{argument}' from its default value", + {"argument": param.name}, + self._function_loc(function))) + if loc is not None: + notes.append(self._call_site_note(loc, is_syscall)) - def proxy_diagnostic(diag): - note = diagnostic.Diagnostic("note", - "expanded from here while trying to infer a type for an" - " unannotated optional argument '{argument}' from its default value", - {"argument": param.name}, - self._function_loc(function)) - diag.notes.append(note) - - note = self._call_site_note(loc, is_syscall) - if note: - diag.notes += note - - self.engine.process(diag) - - proxy_engine = diagnostic.Engine() - proxy_engine.process = proxy_diagnostic - Inferencer(engine=proxy_engine).visit(ast) - IntMonomorphizer(engine=proxy_engine).visit(ast) - - return ast.type + with self.engine.context(*notes): + # Try and infer the type from the default value. + # This is tricky, because the default value might not have + # a well-defined type in APython. + # In this case, we bail out, but mention why we do it. + ast = self._quote(param.default, None) + Inferencer(engine=self.engine).visit(ast) + IntMonomorphizer(engine=self.engine).visit(ast) + return ast.type else: # Let the rest of the program decide. return types.TVar() diff --git a/artiq/test/lit/embedding/error_host_only.py b/artiq/test/lit/embedding/error_host_only.py new file mode 100644 index 000000000..2e2eba6db --- /dev/null +++ b/artiq/test/lit/embedding/error_host_only.py @@ -0,0 +1,19 @@ +# RUN: %python -m artiq.compiler.testbench.embedding +diag %s 2>%t +# RUN: OutputCheck %s --file-to-check=%t + +from artiq.language.core import * +from artiq.language.types import * + +class foo: + # CHECK-L: ${LINE:+2}: fatal: this function cannot be called as an RPC + @host_only + def pause(self): + pass + +x = foo() + +@kernel +def entrypoint(): + # CHECK-L: ${LINE:+2}: note: in function called remotely here + # CHECK-L: ${LINE:+1}: note: while inferring a type for an attribute 'pause' of a host object + x.pause()