We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Student T tests fail on GPU [bug]
```self = MultivariateStudentT(df: 1.5, loc: torch.Size([2]), scale_tril: torch.Size([2, 2]))
sample_shape = torch.Size([])

    def rsample(self, sample_shape=torch.Size()):
        shape = self._extended_shape(sample_shape)
        X = torch.empty(shape, dtype=self.df.dtype, device=self.df.device).normal_()
        Z = self._chi2.rsample(sample_shape)
        Y = X * torch.rsqrt(Z / self.df).unsqueeze(-1)
>       return self.loc + self.scale_tril.matmul(Y.unsqueeze(-1)).squeeze(-1)
E       RuntimeError: Expected object of device type cuda but got device type cpu for argument #2 'mat2' in call to _th_mm

pyro/distributions/multivariate_studentt.py:74: RuntimeError
```

This issue was discussed in #2226 - running `make test` on the dev branch errors out for me if running on a machine with cuda. I am guessing this hasn't shown up in the CI because it uses a cpu only machine. 

I think this bug is pretty simple - it happens because, as we can see in the above snippet, y inherits its device from self.df, and in the fixture, self.df is set to a scalar value. This is not converted into a tensor by the tensors_default_to context manager, and so isn't sent to the gpu. 

I fixed this in #2226 by changing the fixture, but @fritzo suggested that it might suggest a missing coercion rather than a change to the fixture, so that change in the PR was reverted and I am opening this issue instead.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `pyro/distributions/multivariate_studentt.py`
Content:
```
1 import math
2 
3 import torch
4 from torch.distributions import constraints
5 from torch.distributions.utils import broadcast_all, lazy_property
6 
7 from pyro.distributions.torch import Chi2
8 from pyro.distributions.torch_distribution import TorchDistribution
9 from pyro.distributions.util import broadcast_shape
10 
11 
12 class MultivariateStudentT(TorchDistribution):
13     """
14     Creates a multivariate Student's t-distribution parameterized by degree of
15     freedom :attr:`df`, mean :attr:`loc` and scale :attr:`scale_tril`.
16 
17     :param ~torch.Tensor df: degrees of freedom
18     :param ~torch.Tensor loc: mean of the distribution
19     :param ~torch.Tensor scale_tril: scale of the distribution, which is
20         a lower triangular matrix with positive diagonal entries
21     """
22     arg_constraints = {'df': constraints.positive,
23                        'loc': constraints.real_vector,
24                        'scale_tril': constraints.lower_cholesky}
25     support = constraints.real_vector
26     has_rsample = True
27 
28     def __init__(self, df, loc, scale_tril, validate_args=None):
29         dim = loc.size(-1)
30         assert scale_tril.shape[-2:] == (dim, dim)
31         df, = broadcast_all(df)
32         batch_shape = broadcast_shape(df.shape, loc.shape[:-1], scale_tril.shape[:-2])
33         event_shape = (dim,)
34         self.df = df.expand(batch_shape)
35         self.loc = loc
36         self.scale_tril = scale_tril
37         self._chi2 = Chi2(self.df)
38         super(MultivariateStudentT, self).__init__(batch_shape, event_shape, validate_args=validate_args)
39 
40     @lazy_property
41     def covariance_matrix(self):
42         # NB: this is not covariance of this distribution;
43         # the actual covariance is df / (df - 2) * covariance_matrix
44         return torch.matmul(self.scale_tril, self.scale_tril.transpose(-1, -2))
45 
46     @lazy_property
47     def precision_matrix(self):
48         identity = torch.eye(self.loc.size(-1), device=self.loc.device, dtype=self.loc.dtype)
49         scale_inv = identity.triangular_solve(self.scale_tril, upper=False).solution.transpose(-1, -2)
50         return torch.matmul(scale_inv.transpose(-1, -2), scale_inv)
51 
52     def expand(self, batch_shape, _instance=None):
53         new = self._get_checked_instance(MultivariateStudentT, _instance)
54         batch_shape = torch.Size(batch_shape)
55         loc_shape = batch_shape + self.event_shape
56         scale_shape = loc_shape + self.event_shape
57         new.df = self.df.expand(batch_shape)
58         new.loc = self.loc.expand(loc_shape)
59         new.scale_tril = self.scale_tril.expand(scale_shape)
60         if 'covariance_matrix' in self.__dict__:
61             new.covariance_matrix = self.covariance_matrix.expand(scale_shape)
62         if 'precision_matrix' in self.__dict__:
63             new.precision_matrix = self.precision_matrix.expand(scale_shape)
64         new._chi2 = self._chi2.expand(batch_shape)
65         super(MultivariateStudentT, new).__init__(batch_shape, self.event_shape, validate_args=False)
66         new._validate_args = self._validate_args
67         return new
68 
69     def rsample(self, sample_shape=torch.Size()):
70         shape = self._extended_shape(sample_shape)
71         X = torch.empty(shape, dtype=self.df.dtype, device=self.df.device).normal_()
72         Z = self._chi2.rsample(sample_shape)
73         Y = X * torch.rsqrt(Z / self.df).unsqueeze(-1)
74         return self.loc + self.scale_tril.matmul(Y.unsqueeze(-1)).squeeze(-1)
75 
76     def log_prob(self, value):
77         if self._validate_args:
78             self._validate_sample(value)
79         n = self.loc.size(-1)
80         y = (value - self.loc).unsqueeze(-1).triangular_solve(self.scale_tril, upper=False).solution.squeeze(-1)
81         Z = (self.scale_tril.diagonal(dim1=-2, dim2=-1).log().sum(-1) +
82              0.5 * n * self.df.log() +
83              0.5 * n * math.log(math.pi) +
84              torch.lgamma(0.5 * self.df) -
85              torch.lgamma(0.5 * (self.df + n)))
86         return -0.5 * (self.df + n) * torch.log1p(y.pow(2).sum(-1) / self.df) - Z
87 
88     @property
89     def mean(self):
90         m = self.loc.clone()
91         m[self.df <= 1, :] = float('nan')
92         return m
93 
94     @property
95     def variance(self):
96         m = self.scale_tril.pow(2).sum(-1) * (self.df / (self.df - 2)).unsqueeze(-1)
97         m[(self.df <= 2) & (self.df > 1), :] = float('inf')
98         m[self.df <= 1, :] = float('nan')
99         return m
100
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/pyro/distributions/multivariate_studentt.py b/pyro/distributions/multivariate_studentt.py
--- a/pyro/distributions/multivariate_studentt.py
+++ b/pyro/distributions/multivariate_studentt.py
@@ -2,7 +2,7 @@
 
 import torch
 from torch.distributions import constraints
-from torch.distributions.utils import broadcast_all, lazy_property
+from torch.distributions.utils import lazy_property
 
 from pyro.distributions.torch import Chi2
 from pyro.distributions.torch_distribution import TorchDistribution
@@ -28,7 +28,8 @@
     def __init__(self, df, loc, scale_tril, validate_args=None):
         dim = loc.size(-1)
         assert scale_tril.shape[-2:] == (dim, dim)
-        df, = broadcast_all(df)
+        if not isinstance(df, torch.Tensor):
+            df = loc.new_tensor(df)
         batch_shape = broadcast_shape(df.shape, loc.shape[:-1], scale_tril.shape[:-2])
         event_shape = (dim,)
         self.df = df.expand(batch_shape)

{"golden_diff": "diff --git a/pyro/distributions/multivariate_studentt.py b/pyro/distributions/multivariate_studentt.py\n--- a/pyro/distributions/multivariate_studentt.py\n+++ b/pyro/distributions/multivariate_studentt.py\n@@ -2,7 +2,7 @@\n \n import torch\n from torch.distributions import constraints\n-from torch.distributions.utils import broadcast_all, lazy_property\n+from torch.distributions.utils import lazy_property\n \n from pyro.distributions.torch import Chi2\n from pyro.distributions.torch_distribution import TorchDistribution\n@@ -28,7 +28,8 @@\n     def __init__(self, df, loc, scale_tril, validate_args=None):\n         dim = loc.size(-1)\n         assert scale_tril.shape[-2:] == (dim, dim)\n-        df, = broadcast_all(df)\n+        if not isinstance(df, torch.Tensor):\n+            df = loc.new_tensor(df)\n         batch_shape = broadcast_shape(df.shape, loc.shape[:-1], scale_tril.shape[:-2])\n         event_shape = (dim,)\n         self.df = df.expand(batch_shape)\n", "issue": "Student T tests fail on GPU [bug]\n```self = MultivariateStudentT(df: 1.5, loc: torch.Size([2]), scale_tril: torch.Size([2, 2]))\r\nsample_shape = torch.Size([])\r\n\r\n    def rsample(self, sample_shape=torch.Size()):\r\n        shape = self._extended_shape(sample_shape)\r\n        X = torch.empty(shape, dtype=self.df.dtype, device=self.df.device).normal_()\r\n        Z = self._chi2.rsample(sample_shape)\r\n        Y = X * torch.rsqrt(Z / self.df).unsqueeze(-1)\r\n>       return self.loc + self.scale_tril.matmul(Y.unsqueeze(-1)).squeeze(-1)\r\nE       RuntimeError: Expected object of device type cuda but got device type cpu for argument #2 'mat2' in call to _th_mm\r\n\r\npyro/distributions/multivariate_studentt.py:74: RuntimeError\r\n```\r\n\r\nThis issue was discussed in #2226 - running `make test` on the dev branch errors out for me if running on a machine with cuda. I am guessing this hasn't shown up in the CI because it uses a cpu only machine. \r\n\r\nI think this bug is pretty simple - it happens because, as we can see in the above snippet, y inherits its device from self.df, and in the fixture, self.df is set to a scalar value. This is not converted into a tensor by the tensors_default_to context manager, and so isn't sent to the gpu. \r\n\r\nI fixed this in #2226 by changing the fixture, but @fritzo suggested that it might suggest a missing coercion rather than a change to the fixture, so that change in the PR was reverted and I am opening this issue instead.\r\n\n", "before_files": [{"content": "import math\n\nimport torch\nfrom torch.distributions import constraints\nfrom torch.distributions.utils import broadcast_all, lazy_property\n\nfrom pyro.distributions.torch import Chi2\nfrom pyro.distributions.torch_distribution import TorchDistribution\nfrom pyro.distributions.util import broadcast_shape\n\n\nclass MultivariateStudentT(TorchDistribution):\n    \"\"\"\n    Creates a multivariate Student's t-distribution parameterized by degree of\n    freedom :attr:`df`, mean :attr:`loc` and scale :attr:`scale_tril`.\n\n    :param ~torch.Tensor df: degrees of freedom\n    :param ~torch.Tensor loc: mean of the distribution\n    :param ~torch.Tensor scale_tril: scale of the distribution, which is\n        a lower triangular matrix with positive diagonal entries\n    \"\"\"\n    arg_constraints = {'df': constraints.positive,\n                       'loc': constraints.real_vector,\n                       'scale_tril': constraints.lower_cholesky}\n    support = constraints.real_vector\n    has_rsample = True\n\n    def __init__(self, df, loc, scale_tril, validate_args=None):\n        dim = loc.size(-1)\n        assert scale_tril.shape[-2:] == (dim, dim)\n        df, = broadcast_all(df)\n        batch_shape = broadcast_shape(df.shape, loc.shape[:-1], scale_tril.shape[:-2])\n        event_shape = (dim,)\n        self.df = df.expand(batch_shape)\n        self.loc = loc\n        self.scale_tril = scale_tril\n        self._chi2 = Chi2(self.df)\n        super(MultivariateStudentT, self).__init__(batch_shape, event_shape, validate_args=validate_args)\n\n    @lazy_property\n    def covariance_matrix(self):\n        # NB: this is not covariance of this distribution;\n        # the actual covariance is df / (df - 2) * covariance_matrix\n        return torch.matmul(self.scale_tril, self.scale_tril.transpose(-1, -2))\n\n    @lazy_property\n    def precision_matrix(self):\n        identity = torch.eye(self.loc.size(-1), device=self.loc.device, dtype=self.loc.dtype)\n        scale_inv = identity.triangular_solve(self.scale_tril, upper=False).solution.transpose(-1, -2)\n        return torch.matmul(scale_inv.transpose(-1, -2), scale_inv)\n\n    def expand(self, batch_shape, _instance=None):\n        new = self._get_checked_instance(MultivariateStudentT, _instance)\n        batch_shape = torch.Size(batch_shape)\n        loc_shape = batch_shape + self.event_shape\n        scale_shape = loc_shape + self.event_shape\n        new.df = self.df.expand(batch_shape)\n        new.loc = self.loc.expand(loc_shape)\n        new.scale_tril = self.scale_tril.expand(scale_shape)\n        if 'covariance_matrix' in self.__dict__:\n            new.covariance_matrix = self.covariance_matrix.expand(scale_shape)\n        if 'precision_matrix' in self.__dict__:\n            new.precision_matrix = self.precision_matrix.expand(scale_shape)\n        new._chi2 = self._chi2.expand(batch_shape)\n        super(MultivariateStudentT, new).__init__(batch_shape, self.event_shape, validate_args=False)\n        new._validate_args = self._validate_args\n        return new\n\n    def rsample(self, sample_shape=torch.Size()):\n        shape = self._extended_shape(sample_shape)\n        X = torch.empty(shape, dtype=self.df.dtype, device=self.df.device).normal_()\n        Z = self._chi2.rsample(sample_shape)\n        Y = X * torch.rsqrt(Z / self.df).unsqueeze(-1)\n        return self.loc + self.scale_tril.matmul(Y.unsqueeze(-1)).squeeze(-1)\n\n    def log_prob(self, value):\n        if self._validate_args:\n            self._validate_sample(value)\n        n = self.loc.size(-1)\n        y = (value - self.loc).unsqueeze(-1).triangular_solve(self.scale_tril, upper=False).solution.squeeze(-1)\n        Z = (self.scale_tril.diagonal(dim1=-2, dim2=-1).log().sum(-1) +\n             0.5 * n * self.df.log() +\n             0.5 * n * math.log(math.pi) +\n             torch.lgamma(0.5 * self.df) -\n             torch.lgamma(0.5 * (self.df + n)))\n        return -0.5 * (self.df + n) * torch.log1p(y.pow(2).sum(-1) / self.df) - Z\n\n    @property\n    def mean(self):\n        m = self.loc.clone()\n        m[self.df <= 1, :] = float('nan')\n        return m\n\n    @property\n    def variance(self):\n        m = self.scale_tril.pow(2).sum(-1) * (self.df / (self.df - 2)).unsqueeze(-1)\n        m[(self.df <= 2) & (self.df > 1), :] = float('inf')\n        m[self.df <= 1, :] = float('nan')\n        return m\n", "path": "pyro/distributions/multivariate_studentt.py"}], "after_files": [{"content": "import math\n\nimport torch\nfrom torch.distributions import constraints\nfrom torch.distributions.utils import lazy_property\n\nfrom pyro.distributions.torch import Chi2\nfrom pyro.distributions.torch_distribution import TorchDistribution\nfrom pyro.distributions.util import broadcast_shape\n\n\nclass MultivariateStudentT(TorchDistribution):\n    \"\"\"\n    Creates a multivariate Student's t-distribution parameterized by degree of\n    freedom :attr:`df`, mean :attr:`loc` and scale :attr:`scale_tril`.\n\n    :param ~torch.Tensor df: degrees of freedom\n    :param ~torch.Tensor loc: mean of the distribution\n    :param ~torch.Tensor scale_tril: scale of the distribution, which is\n        a lower triangular matrix with positive diagonal entries\n    \"\"\"\n    arg_constraints = {'df': constraints.positive,\n                       'loc': constraints.real_vector,\n                       'scale_tril': constraints.lower_cholesky}\n    support = constraints.real_vector\n    has_rsample = True\n\n    def __init__(self, df, loc, scale_tril, validate_args=None):\n        dim = loc.size(-1)\n        assert scale_tril.shape[-2:] == (dim, dim)\n        if not isinstance(df, torch.Tensor):\n            df = loc.new_tensor(df)\n        batch_shape = broadcast_shape(df.shape, loc.shape[:-1], scale_tril.shape[:-2])\n        event_shape = (dim,)\n        self.df = df.expand(batch_shape)\n        self.loc = loc\n        self.scale_tril = scale_tril\n        self._chi2 = Chi2(self.df)\n        super(MultivariateStudentT, self).__init__(batch_shape, event_shape, validate_args=validate_args)\n\n    @lazy_property\n    def covariance_matrix(self):\n        # NB: this is not covariance of this distribution;\n        # the actual covariance is df / (df - 2) * covariance_matrix\n        return torch.matmul(self.scale_tril, self.scale_tril.transpose(-1, -2))\n\n    @lazy_property\n    def precision_matrix(self):\n        identity = torch.eye(self.loc.size(-1), device=self.loc.device, dtype=self.loc.dtype)\n        scale_inv = identity.triangular_solve(self.scale_tril, upper=False).solution.transpose(-1, -2)\n        return torch.matmul(scale_inv.transpose(-1, -2), scale_inv)\n\n    def expand(self, batch_shape, _instance=None):\n        new = self._get_checked_instance(MultivariateStudentT, _instance)\n        batch_shape = torch.Size(batch_shape)\n        loc_shape = batch_shape + self.event_shape\n        scale_shape = loc_shape + self.event_shape\n        new.df = self.df.expand(batch_shape)\n        new.loc = self.loc.expand(loc_shape)\n        new.scale_tril = self.scale_tril.expand(scale_shape)\n        if 'covariance_matrix' in self.__dict__:\n            new.covariance_matrix = self.covariance_matrix.expand(scale_shape)\n        if 'precision_matrix' in self.__dict__:\n            new.precision_matrix = self.precision_matrix.expand(scale_shape)\n        new._chi2 = self._chi2.expand(batch_shape)\n        super(MultivariateStudentT, new).__init__(batch_shape, self.event_shape, validate_args=False)\n        new._validate_args = self._validate_args\n        return new\n\n    def rsample(self, sample_shape=torch.Size()):\n        shape = self._extended_shape(sample_shape)\n        X = torch.empty(shape, dtype=self.df.dtype, device=self.df.device).normal_()\n        Z = self._chi2.rsample(sample_shape)\n        Y = X * torch.rsqrt(Z / self.df).unsqueeze(-1)\n        return self.loc + self.scale_tril.matmul(Y.unsqueeze(-1)).squeeze(-1)\n\n    def log_prob(self, value):\n        if self._validate_args:\n            self._validate_sample(value)\n        n = self.loc.size(-1)\n        y = (value - self.loc).unsqueeze(-1).triangular_solve(self.scale_tril, upper=False).solution.squeeze(-1)\n        Z = (self.scale_tril.diagonal(dim1=-2, dim2=-1).log().sum(-1) +\n             0.5 * n * self.df.log() +\n             0.5 * n * math.log(math.pi) +\n             torch.lgamma(0.5 * self.df) -\n             torch.lgamma(0.5 * (self.df + n)))\n        return -0.5 * (self.df + n) * torch.log1p(y.pow(2).sum(-1) / self.df) - Z\n\n    @property\n    def mean(self):\n        m = self.loc.clone()\n        m[self.df <= 1, :] = float('nan')\n        return m\n\n    @property\n    def variance(self):\n        m = self.scale_tril.pow(2).sum(-1) * (self.df / (self.df - 2)).unsqueeze(-1)\n        m[(self.df <= 2) & (self.df > 1), :] = float('inf')\n        m[self.df <= 1, :] = float('nan')\n        return m\n", "path": "pyro/distributions/multivariate_studentt.py"}]}