Repository: Qiskit/qiskit

Issue:
transpiler pass return value is still ignored
### Informations

- **Qiskit Terra version**: 0.7.0
- **Python version**: 3.7.0
- **Operating system**: Mac OS 10.13.6

### What is the current behavior?

The transpile method [here](https://github.com/Qiskit/qiskit-terra/blob/master/qiskit/transpiler/_transpiler.py#L339) relies on the pass manager to modify the DAG in place.  The pass manager uses the values returned by the passes and then discards them.  See [here](https://github.com/Qiskit/qiskit-terra/blob/master/qiskit/transpiler/_passmanager.py#L107).  See also #897 

### Steps to reproduce the problem

```
from qiskit.wrapper import load_qasm_string
from qiskit.dagcircuit import DAGCircuit
from qiskit.transpiler import PassManager, transpile
from qiskit.transpiler._basepasses import TransformationPass

class BugPass(TransformationPass) :
    
    def run(self, dag):
        print("Activating")
        return DAGCircuit()

qasm = "OPENQASM 2.0;\ninclude \"qelib1.inc\";\nqreg q[2];\nh q[0];\ncx q[0],q[1];"
dag = DAGCircuit.fromQuantumCircuit(load_qasm_string(qasm))
pm = PassManager()
pm.add_passes(BugPass())

dag2 = transpile(dag,pass_manager=pm)

dag == dag2 # returns true but should be false
```

### What is the expected behavior?

The transpiler should use the values returned by the passes.

### Suggested solutions

Make PassManager.run_passes() return a DAG.  Make transpile() use this return value.



Discussion:
The reason for `dag == dag2` it is because they are the same:
```
class BugPass(TransformationPass) :
    
    def run(self, dag):
        dag.property = 42
        return DAGCircuit()

pm.add_passes(BugPass())
transpile(dag,pass_manager=pm)

dag.property # 42
```
However, I do think the new transpiler should return something: the property set. What do you think @ajavadia?
This is a bug. `dag` should not be equal to `dag2`, as the TransformationPass is changing it (taking a non-empty dag and returning an empty dag).

The bug comes from exactly what is described. The PassManager is internally catching the returned DAG from each pass and passing it to the next pass, but once all passes finish, the final DAG is not propagated up to the `transpiler.transpile()`. So it looks like nothing happened.
I continue recommending the [DAG to be an immutable container](https://github.com/Qiskit/qiskit-terra/issues/825#issuecomment-421964618) but for that, the DAG and DAG-building APIs should be thoroughly reworked.

Resolving patch:
diff --git a/qiskit/transpiler/_passmanager.py b/qiskit/transpiler/_passmanager.py
--- a/qiskit/transpiler/_passmanager.py
+++ b/qiskit/transpiler/_passmanager.py
@@ -105,14 +105,18 @@ def add_passes(self, passes, ignore_requires=None, ignore_preserves=None, max_it
             FlowController.controller_factory(passes, options, **flow_controller_conditions))
 
     def run_passes(self, dag):
-        """Run all the passes on the dag.
+        """Run all the passes on a DAG.
 
         Args:
-            dag (DAGCircuit): dag circuit to transform via all the registered passes
+            dag (DAGCircuit): DAG circuit to transform via all the registered passes
+
+        Returns:
+            DAGCircuit: Transformed DAG.
         """
         for passset in self.working_list:
             for pass_ in passset:
                 dag = self._do_pass(pass_, dag, passset.options)
+        return dag
 
     def _do_pass(self, pass_, dag, options):
         """Do a pass and its "requires".
diff --git a/qiskit/transpiler/_transpiler.py b/qiskit/transpiler/_transpiler.py
--- a/qiskit/transpiler/_transpiler.py
+++ b/qiskit/transpiler/_transpiler.py
@@ -336,7 +336,8 @@ def transpile(dag, basis_gates='u1,u2,u3,cx,id', coupling_map=None,
 
     if pass_manager:
         # run the passes specified by the pass manager
-        pass_manager.run_passes(dag)
+        # TODO return the property set too. See #1086
+        dag = pass_manager.run_passes(dag)
     else:
         # default set of passes
         # TODO: move each step here to a pass, and use a default passmanager below


Test patch:
diff --git a/test/python/transpiler/test_pass_scheduler.py b/test/python/transpiler/test_pass_scheduler.py
--- a/test/python/transpiler/test_pass_scheduler.py
+++ b/test/python/transpiler/test_pass_scheduler.py
@@ -36,7 +36,8 @@ def assertScheduler(self, dag, passmanager, expected):
             expected (list): List of things the passes are logging
         """
         with self.assertLogs(logger, level='INFO') as cm:
-            transpile(dag, pass_manager=passmanager)
+            dag = transpile(dag, pass_manager=passmanager)
+        self.assertIsInstance(dag, DAGCircuit)
         self.assertEqual([record.message for record in cm.records], expected)
 
     def assertSchedulerRaises(self, dag, passmanager, expected, exception_type):