diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index dde4237aa48..1288de9fa22 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -1947,9 +1947,16 @@ mod unify { variance: variance) -> option::t<(ast::mutability, variance)> { - // If you're unifying mutability then the thing inside - // will be invariant on anything it contains - let newvariance = variance_transform(variance, invariant); + // If you're unifying on something mutable then we have to + // be invariant on the inner type + let newvariance = alt expected { + ast::mut. { + variance_transform(variance, invariant) + } + _ { + variance_transform(variance, covariant) + } + }; if expected == actual { ret some((expected, newvariance)); } if variance == covariant { diff --git a/src/test/run-pass/mutable-huh-variance-vec1.rs b/src/test/run-pass/mutable-huh-variance-vec1.rs new file mode 100644 index 00000000000..5fb49cf88ce --- /dev/null +++ b/src/test/run-pass/mutable-huh-variance-vec1.rs @@ -0,0 +1,13 @@ +// error-pattern: mismatched types + +fn main() { + let v = [[0]]; + + // This is ok because the outer vec is covariant with respect + // to the inner vec. If the outer vec was mutable then we + // couldn't do this. + fn f(&&v: [[mutable? int]]) { + } + + f(v); +} diff --git a/src/test/run-pass/mutable-huh-variance-vec2.rs b/src/test/run-pass/mutable-huh-variance-vec2.rs new file mode 100644 index 00000000000..1e254e86806 --- /dev/null +++ b/src/test/run-pass/mutable-huh-variance-vec2.rs @@ -0,0 +1,13 @@ +// error-pattern: mismatched types + +fn main() { + let v = [[0]]; + + // This is ok because the outer vec is covariant with respect + // to the inner vec. If the outer vec was mutable then we + // couldn't do this. + fn f(&&v: [mutable? [mutable? int]]) { + } + + f(v); +}