diff --git a/compiler/rustc_infer/src/infer/relate/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs index b2d591327fea2..5bbddde9f76b3 100644 --- a/compiler/rustc_infer/src/infer/relate/generalize.rs +++ b/compiler/rustc_infer/src/infer/relate/generalize.rs @@ -68,7 +68,37 @@ impl<'tcx> InferCtxt<'tcx> { let normalized_alias = relation.try_eagerly_normalize_alias(*alias); if normalized_alias.is_ty_var() { - normalized_alias + // If normalization returns an infer var, we shouldn't directly output it. + // This can cause us to wrongly assume that another type is *exactly equal* + // to the alias that this infer var represents, while it may actually be a subtype. + // Unless the variance is invariant, we therefore generate a new infer var, + // with a subtyping relation to the infer var returned by normalization. + match instantiation_variance { + ty::Invariant => normalized_alias, + ty::Covariant => { + let new_tyvar = self.next_ty_var(relation.span()); + relation.register_predicates([ty::PredicateKind::Subtype( + ty::SubtypePredicate { + a_is_expected: true, + a: new_tyvar, + b: normalized_alias, + }, + )]); + new_tyvar + } + ty::Contravariant => { + let new_tyvar = self.next_ty_var(relation.span()); + relation.register_predicates([ty::PredicateKind::Subtype( + ty::SubtypePredicate { + a_is_expected: true, + a: normalized_alias, + b: new_tyvar, + }, + )]); + new_tyvar + } + ty::Bivariant => unreachable!("bivariant generalization"), + } } else { let Generalization { value_may_be_infer: generalized_ty } = self.generalize( relation.span(), diff --git a/tests/ui/impl-trait/unsized_coercion.next.stderr b/tests/ui/impl-trait/unsized_coercion.next.stderr new file mode 100644 index 0000000000000..4cebd26a5bee6 --- /dev/null +++ b/tests/ui/impl-trait/unsized_coercion.next.stderr @@ -0,0 +1,35 @@ +error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time + --> $DIR/unsized_coercion.rs:15:17 + | +LL | let x = hello(); + | ^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `dyn Trait` + +error[E0308]: mismatched types + --> $DIR/unsized_coercion.rs:19:5 + | +LL | fn hello() -> Box { + | --------------- + | | | + | | the expected opaque type + | expected `Box` because of return type +... +LL | Box::new(1u32) + | ^^^^^^^^^^^^^^ types differ + | + = note: expected struct `Box` + found struct `Box` + +error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time + --> $DIR/unsized_coercion.rs:12:1 + | +LL | fn hello() -> Box { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `dyn Trait` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/unsized_coercion.rs b/tests/ui/impl-trait/unsized_coercion.rs index f77f2198be0ef..bb81dd77ac511 100644 --- a/tests/ui/impl-trait/unsized_coercion.rs +++ b/tests/ui/impl-trait/unsized_coercion.rs @@ -3,18 +3,21 @@ //@ revisions: next old //@[next] compile-flags: -Znext-solver -//@ check-pass +//@[old] check-pass trait Trait {} impl Trait for u32 {} fn hello() -> Box { + //[next]~^ ERROR: the size for values of type `dyn Trait` cannot be known at compilation time if true { let x = hello(); + //[next]~^ ERROR: the size for values of type `dyn Trait` cannot be known at compilation time let y: Box = x; } Box::new(1u32) + //[next]~^ ERROR: mismatched types } fn main() {} diff --git a/tests/ui/impl-trait/unsized_coercion3.next.stderr b/tests/ui/impl-trait/unsized_coercion3.next.stderr index db758761d7954..3516d1906ea20 100644 --- a/tests/ui/impl-trait/unsized_coercion3.next.stderr +++ b/tests/ui/impl-trait/unsized_coercion3.next.stderr @@ -9,8 +9,6 @@ help: the trait `Trait` is implemented for `u32` | LL | impl Trait for u32 {} | ^^^^^^^^^^^^^^^^^^ -note: required by a bound in `Box` - --> $SRC_DIR/alloc/src/boxed.rs:LL:COL error[E0308]: mismatched types --> $DIR/unsized_coercion3.rs:19:5