diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 7ea21b24fc821..8bcdd44ccbedd 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -138,6 +138,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { let name_str = intrinsic_name.as_str(); let bound_vars = tcx.mk_bound_variable_kinds(&[ + ty::BoundVariableKind::Region(ty::BrAnon), ty::BoundVariableKind::Region(ty::BrAnon), ty::BoundVariableKind::Region(ty::BrEnv), ]); @@ -151,7 +152,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { let env_region = ty::Region::new_bound( tcx, ty::INNERMOST, - ty::BoundRegion { var: ty::BoundVar::from_u32(1), kind: ty::BrEnv }, + ty::BoundRegion { var: ty::BoundVar::from_u32(2), kind: ty::BrEnv }, ); let va_list_ty = tcx.type_of(did).instantiate(tcx, &[region.into()]); (Ty::new_ref(tcx, env_region, ty::TypeAndMut { ty: va_list_ty, mutbl }), va_list_ty) @@ -446,9 +447,12 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { sym::raw_eq => { let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon }; - let param_ty = + let param_ty_lhs = + Ty::new_imm_ref(tcx, ty::Region::new_bound(tcx, ty::INNERMOST, br), param(0)); + let br = ty::BoundRegion { var: ty::BoundVar::from_u32(1), kind: ty::BrAnon }; + let param_ty_rhs = Ty::new_imm_ref(tcx, ty::Region::new_bound(tcx, ty::INNERMOST, br), param(0)); - (1, vec![param_ty; 2], tcx.types.bool) + (1, vec![param_ty_lhs, param_ty_rhs], tcx.types.bool) } sym::black_box => (1, vec![param(0)], param(0)), diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs index 759ebaa1d1e5b..dfae279324f1c 100644 --- a/compiler/rustc_infer/src/infer/combine.rs +++ b/compiler/rustc_infer/src/infer/combine.rs @@ -34,6 +34,7 @@ use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue, EffectVa use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::relate::{RelateResult, TypeRelation}; +use rustc_middle::ty::TyVar; use rustc_middle::ty::{self, InferConst, ToPredicate, Ty, TyCtxt, TypeVisitableExt}; use rustc_middle::ty::{IntType, UintType}; use rustc_span::DUMMY_SP; @@ -459,7 +460,12 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> { ambient_variance, )?; - self.infcx.inner.borrow_mut().type_variables().instantiate(b_vid, b_ty); + // Constrain `b_vid` to the generalized type `b_ty`. + if let &ty::Infer(TyVar(b_ty_vid)) = b_ty.kind() { + self.infcx.inner.borrow_mut().type_variables().equate(b_vid, b_ty_vid); + } else { + self.infcx.inner.borrow_mut().type_variables().instantiate(b_vid, b_ty); + } if needs_wf { self.obligations.push(Obligation::new( diff --git a/compiler/rustc_infer/src/infer/equate.rs b/compiler/rustc_infer/src/infer/equate.rs index 5d929394eb04c..2483a17066d96 100644 --- a/compiler/rustc_infer/src/infer/equate.rs +++ b/compiler/rustc_infer/src/infer/equate.rs @@ -165,8 +165,8 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> { } if a.skip_binder().has_escaping_bound_vars() || b.skip_binder().has_escaping_bound_vars() { - self.fields.higher_ranked_sub(a, b, self.a_is_expected)?; - self.fields.higher_ranked_sub(b, a, self.a_is_expected)?; + self.fields.higher_ranked_equate(a, b, self.a_is_expected)?; + self.fields.higher_ranked_equate(b, a, !self.a_is_expected)?; } else { // Fast path for the common case. self.relate(a.skip_binder(), b.skip_binder())?; diff --git a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs index 510b1797d3c9b..4019e2df85f82 100644 --- a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs +++ b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs @@ -57,6 +57,40 @@ impl<'a, 'tcx> CombineFields<'a, 'tcx> { // placeholders which **must not** be named afterwards. Ok(()) } + + #[instrument(skip(self), level = "debug")] + pub fn higher_ranked_equate( + &mut self, + a: Binder<'tcx, T>, + b: Binder<'tcx, T>, + a_is_expected: bool, + ) -> RelateResult<'tcx, ()> + where + T: Relate<'tcx>, + { + let span = self.trace.cause.span; + // First, we instantiate each bound region in the supertype with a + // fresh placeholder region. Note that this automatically creates + // a new universe if needed. + let b_prime = self.infcx.instantiate_binder_with_placeholders(b); + + // Next, we instantiate each bound region in the subtype + // with a fresh region variable. These region variables -- + // but no other preexisting region variables -- can name + // the placeholders. + let a_prime = self.infcx.instantiate_binder_with_fresh_vars(span, HigherRankedType, a); + + debug!("a_prime={:?}", a_prime); + debug!("b_prime={:?}", b_prime); + + // Compare types now that bound regions have been replaced. + let result = self.equate(a_is_expected).relate(a_prime, b_prime)?; + + debug!("OK result={result:?}"); + // NOTE: returning the result here would be dangerous as it contains + // placeholders which **must not** be named afterwards. + Ok(()) + } } impl<'tcx> InferCtxt<'tcx> { diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs index d707c30206df9..e8d8e9e912d53 100644 --- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs +++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs @@ -603,61 +603,78 @@ where return Ok(ty::Binder::dummy(a)); } - if self.ambient_covariance() { - // Covariance, so we want `for<..> A <: for<..> B` -- - // therefore we compare any instantiation of A (i.e., A - // instantiated with existentials) against every - // instantiation of B (i.e., B instantiated with - // universals). - - // Reset the ambient variance to covariant. This is needed - // to correctly handle cases like - // - // for<'a> fn(&'a u32, &'a u32) == for<'b, 'c> fn(&'b u32, &'c u32) - // - // Somewhat surprisingly, these two types are actually - // **equal**, even though the one on the right looks more - // polymorphic. The reason is due to subtyping. To see it, - // consider that each function can call the other: - // - // - The left function can call the right with `'b` and - // `'c` both equal to `'a` - // - // - The right function can call the left with `'a` set to - // `{P}`, where P is the point in the CFG where the call - // itself occurs. Note that `'b` and `'c` must both - // include P. At the point, the call works because of - // subtyping (i.e., `&'b u32 <: &{P} u32`). - let variance = std::mem::replace(&mut self.ambient_variance, ty::Variance::Covariant); - - // Note: the order here is important. Create the placeholders first, otherwise - // we assign the wrong universe to the existential! - let b_replaced = self.instantiate_binder_with_placeholders(b); - let a_replaced = self.instantiate_binder_with_existentials(a); - - self.relate(a_replaced, b_replaced)?; - - self.ambient_variance = variance; - } + match self.ambient_variance { + ty::Variance::Covariant => { + // Covariance, so we want `for<..> A <: for<..> B` -- + // therefore we compare any instantiation of A (i.e., A + // instantiated with existentials) against every + // instantiation of B (i.e., B instantiated with + // universals). + + // Reset the ambient variance to covariant. This is needed + // to correctly handle cases like + // + // for<'a> fn(&'a u32, &'a u32) == for<'b, 'c> fn(&'b u32, &'c u32) + // + // Somewhat surprisingly, these two types are actually + // **equal**, even though the one on the right looks more + // polymorphic. The reason is due to subtyping. To see it, + // consider that each function can call the other: + // + // - The left function can call the right with `'b` and + // `'c` both equal to `'a` + // + // - The right function can call the left with `'a` set to + // `{P}`, where P is the point in the CFG where the call + // itself occurs. Note that `'b` and `'c` must both + // include P. At the point, the call works because of + // subtyping (i.e., `&'b u32 <: &{P} u32`). + let variance = + std::mem::replace(&mut self.ambient_variance, ty::Variance::Covariant); + + // Note: the order here is important. Create the placeholders first, otherwise + // we assign the wrong universe to the existential! + let b_replaced = self.instantiate_binder_with_placeholders(b); + let a_replaced = self.instantiate_binder_with_existentials(a); + + self.relate(a_replaced, b_replaced)?; + + self.ambient_variance = variance; + } - if self.ambient_contravariance() { - // Contravariance, so we want `for<..> A :> for<..> B` - // -- therefore we compare every instantiation of A (i.e., - // A instantiated with universals) against any - // instantiation of B (i.e., B instantiated with - // existentials). Opposite of above. + ty::Variance::Contravariant => { + // Contravariance, so we want `for<..> A :> for<..> B` + // -- therefore we compare every instantiation of A (i.e., + // A instantiated with universals) against any + // instantiation of B (i.e., B instantiated with + // existentials). Opposite of above. - // Reset ambient variance to contravariance. See the - // covariant case above for an explanation. - let variance = - std::mem::replace(&mut self.ambient_variance, ty::Variance::Contravariant); + // Reset ambient variance to contravariance. See the + // covariant case above for an explanation. + let variance = + std::mem::replace(&mut self.ambient_variance, ty::Variance::Contravariant); - let a_replaced = self.instantiate_binder_with_placeholders(a); - let b_replaced = self.instantiate_binder_with_existentials(b); + let a_replaced = self.instantiate_binder_with_placeholders(a); + let b_replaced = self.instantiate_binder_with_existentials(b); - self.relate(a_replaced, b_replaced)?; + self.relate(a_replaced, b_replaced)?; + + self.ambient_variance = variance; + } + + ty::Variance::Invariant => { + // Note: the order here is important. Create the placeholders first, otherwise + // we assign the wrong universe to the existential! + let b_replaced = self.instantiate_binder_with_placeholders(b); + let a_replaced = self.instantiate_binder_with_existentials(a); + self.relate(a_replaced, b_replaced)?; + + let a_replaced = self.instantiate_binder_with_placeholders(a); + let b_replaced = self.instantiate_binder_with_existentials(b); + self.relate(a_replaced, b_replaced)?; + } - self.ambient_variance = variance; + ty::Variance::Bivariant => {} } Ok(a) diff --git a/compiler/rustc_infer/src/infer/type_variable.rs b/compiler/rustc_infer/src/infer/type_variable.rs index bc83f8d3f9676..bd6f905c8241d 100644 --- a/compiler/rustc_infer/src/infer/type_variable.rs +++ b/compiler/rustc_infer/src/infer/type_variable.rs @@ -229,12 +229,11 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> { /// Precondition: `vid` must not have been previously instantiated. pub fn instantiate(&mut self, vid: ty::TyVid, ty: Ty<'tcx>) { let vid = self.root_var(vid); + debug_assert!(!ty.is_ty_var(), "instantiating ty var with var: {vid:?} {ty:?}"); debug_assert!(self.probe(vid).is_unknown()); debug_assert!( self.eq_relations().probe_value(vid).is_unknown(), - "instantiating type variable `{:?}` twice: new-value = {:?}, old-value={:?}", - vid, - ty, + "instantiating type variable `{vid:?}` twice: new-value = {ty:?}, old-value={:?}", self.eq_relations().probe_value(vid) ); self.eq_relations().union_value(vid, TypeVariableValue::Known { value: ty }); diff --git a/tests/ui/associated-inherent-types/issue-111404-1.rs b/tests/ui/associated-inherent-types/issue-111404-1.rs index dd62e59f07d22..472666381ee28 100644 --- a/tests/ui/associated-inherent-types/issue-111404-1.rs +++ b/tests/ui/associated-inherent-types/issue-111404-1.rs @@ -8,7 +8,7 @@ impl<'a> Foo { } fn bar(_: fn(Foo fn(Foo::Assoc)>::Assoc)) {} -//~^ ERROR higher-ranked subtype error -//~| ERROR higher-ranked subtype error +//~^ ERROR mismatched types [E0308] +//~| ERROR mismatched types [E0308] fn main() {} diff --git a/tests/ui/associated-inherent-types/issue-111404-1.stderr b/tests/ui/associated-inherent-types/issue-111404-1.stderr index cf4d4a5f19b12..5351f43a7ef81 100644 --- a/tests/ui/associated-inherent-types/issue-111404-1.stderr +++ b/tests/ui/associated-inherent-types/issue-111404-1.stderr @@ -1,16 +1,22 @@ -error: higher-ranked subtype error - --> $DIR/issue-111404-1.rs:10:1 +error[E0308]: mismatched types + --> $DIR/issue-111404-1.rs:10:11 | LL | fn bar(_: fn(Foo fn(Foo::Assoc)>::Assoc)) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected struct `Foo` + found struct `Foo fn(&'b ())>` -error: higher-ranked subtype error - --> $DIR/issue-111404-1.rs:10:1 +error[E0308]: mismatched types + --> $DIR/issue-111404-1.rs:10:11 | LL | fn bar(_: fn(Foo fn(Foo::Assoc)>::Assoc)) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other | + = note: expected struct `Foo` + found struct `Foo fn(&'b ())>` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/closure-expected-type/expect-fn-supply-fn.rs b/tests/ui/closure-expected-type/expect-fn-supply-fn.rs index 7f1c140279c4e..7599d07835116 100644 --- a/tests/ui/closure-expected-type/expect-fn-supply-fn.rs +++ b/tests/ui/closure-expected-type/expect-fn-supply-fn.rs @@ -30,14 +30,16 @@ fn expect_free_supply_bound() { // Here, we are given a function whose region is bound at closure level, // but we expect one bound in the argument. Error results. with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {}); - //~^ ERROR mismatched types + //~^ ERROR mismatched types [E0308] + //~| ERROR lifetime may not live long enough } fn expect_bound_supply_free_from_fn<'x>(x: &'x u32) { // Here, we are given a `fn(&u32)` but we expect a `fn(&'x // u32)`. In principle, this could be ok, but we demand equality. with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {}); - //~^ ERROR mismatched types + //~^ ERROR mismatched types [E0308] + //~| ERROR lifetime may not live long enough } fn expect_bound_supply_free_from_closure() { diff --git a/tests/ui/closure-expected-type/expect-fn-supply-fn.stderr b/tests/ui/closure-expected-type/expect-fn-supply-fn.stderr index e6ddc60689779..68cac2e2d051d 100644 --- a/tests/ui/closure-expected-type/expect-fn-supply-fn.stderr +++ b/tests/ui/closure-expected-type/expect-fn-supply-fn.stderr @@ -19,6 +19,15 @@ LL | fn expect_free_supply_free_from_fn<'x>(x: &'x u32) { LL | with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {}); | ^ requires that `'x` must outlive `'static` +error: lifetime may not live long enough + --> $DIR/expect-fn-supply-fn.rs:32:49 + | +LL | with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {}); + | ^ + | | + | has type `fn(&'1 u32)` + | requires that `'1` must outlive `'static` + error[E0308]: mismatched types --> $DIR/expect-fn-supply-fn.rs:32:49 | @@ -29,7 +38,7 @@ LL | with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {}); found fn pointer `for<'a> fn(&'a u32)` error[E0308]: mismatched types - --> $DIR/expect-fn-supply-fn.rs:39:50 + --> $DIR/expect-fn-supply-fn.rs:40:50 | LL | with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {}); | ^ one type is more general than the other @@ -37,8 +46,17 @@ LL | with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {}); = note: expected fn pointer `for<'a> fn(&'a u32)` found fn pointer `fn(&u32)` +error: lifetime may not live long enough + --> $DIR/expect-fn-supply-fn.rs:40:50 + | +LL | fn expect_bound_supply_free_from_fn<'x>(x: &'x u32) { + | -- lifetime `'x` defined here +... +LL | with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {}); + | ^ requires that `'x` must outlive `'static` + error[E0308]: mismatched types - --> $DIR/expect-fn-supply-fn.rs:48:50 + --> $DIR/expect-fn-supply-fn.rs:50:50 | LL | with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, y| { | ^ one type is more general than the other @@ -46,6 +64,6 @@ LL | with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, y| { = note: expected fn pointer `for<'a> fn(&'a u32)` found fn pointer `fn(&u32)` -error: aborting due to 5 previous errors +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/coherence/coherence-fn-covariant-bound-vs-static.rs b/tests/ui/coherence/coherence-fn-covariant-bound-vs-static.rs index 99f805f7f0f63..b37d1639f9d34 100644 --- a/tests/ui/coherence/coherence-fn-covariant-bound-vs-static.rs +++ b/tests/ui/coherence/coherence-fn-covariant-bound-vs-static.rs @@ -1,3 +1,5 @@ +// check-pass + // Test that impls for these two types are considered ovelapping: // // * `for<'r> fn(fn(&'r u32))` @@ -15,7 +17,8 @@ trait Trait {} impl Trait for for<'r> fn(fn(&'r ())) {} impl<'a> Trait for fn(fn(&'a ())) {} -//~^ ERROR conflicting implementations +//~^ WARN conflicting implementations of trait `Trait` for type `for<'r> fn(fn(&'r ()))` [coherence_leak_check] +//~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! // // Note in particular that we do NOT get a future-compatibility warning // here. This is because the new leak-check proposed in [MCP 295] does not diff --git a/tests/ui/coherence/coherence-fn-covariant-bound-vs-static.stderr b/tests/ui/coherence/coherence-fn-covariant-bound-vs-static.stderr index 316da26b54d4a..ebe7366b9458b 100644 --- a/tests/ui/coherence/coherence-fn-covariant-bound-vs-static.stderr +++ b/tests/ui/coherence/coherence-fn-covariant-bound-vs-static.stderr @@ -1,13 +1,15 @@ -error[E0119]: conflicting implementations of trait `Trait` for type `for<'r> fn(fn(&'r ()))` - --> $DIR/coherence-fn-covariant-bound-vs-static.rs:17:1 +warning: conflicting implementations of trait `Trait` for type `for<'r> fn(fn(&'r ()))` + --> $DIR/coherence-fn-covariant-bound-vs-static.rs:19:1 | LL | impl Trait for for<'r> fn(fn(&'r ())) {} | ------------------------------------- first implementation here LL | impl<'a> Trait for fn(fn(&'a ())) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'r> fn(fn(&'r ()))` | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #56105 = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details + = note: `#[warn(coherence_leak_check)]` on by default -error: aborting due to 1 previous error +warning: 1 warning emitted -For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-fn-inputs.rs b/tests/ui/coherence/coherence-fn-inputs.rs index 3afec5c5459af..c351553c0adcd 100644 --- a/tests/ui/coherence/coherence-fn-inputs.rs +++ b/tests/ui/coherence/coherence-fn-inputs.rs @@ -1,3 +1,5 @@ +// check-pass + // Test that we consider these two types completely equal: // // * `for<'a, 'b> fn(&'a u32, &'b u32)` @@ -13,7 +15,8 @@ trait Trait {} impl Trait for for<'a, 'b> fn(&'a u32, &'b u32) {} impl Trait for for<'c> fn(&'c u32, &'c u32) { - //~^ ERROR conflicting implementations + //~^ WARN conflicting implementations of trait `Trait` for type `for<'a, 'b> fn(&'a u32, &'b u32)` [coherence_leak_check] + //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! // // Note in particular that we do NOT get a future-compatibility warning // here. This is because the new leak-check proposed in [MCP 295] does not diff --git a/tests/ui/coherence/coherence-fn-inputs.stderr b/tests/ui/coherence/coherence-fn-inputs.stderr index 246ec5947b3e4..b00f1704f9481 100644 --- a/tests/ui/coherence/coherence-fn-inputs.stderr +++ b/tests/ui/coherence/coherence-fn-inputs.stderr @@ -1,13 +1,15 @@ -error[E0119]: conflicting implementations of trait `Trait` for type `for<'a, 'b> fn(&'a u32, &'b u32)` - --> $DIR/coherence-fn-inputs.rs:15:1 +warning: conflicting implementations of trait `Trait` for type `for<'a, 'b> fn(&'a u32, &'b u32)` + --> $DIR/coherence-fn-inputs.rs:17:1 | LL | impl Trait for for<'a, 'b> fn(&'a u32, &'b u32) {} | ----------------------------------------------- first implementation here LL | impl Trait for for<'c> fn(&'c u32, &'c u32) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'a, 'b> fn(&'a u32, &'b u32)` | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #56105 = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details + = note: `#[warn(coherence_leak_check)]` on by default -error: aborting due to 1 previous error +warning: 1 warning emitted -For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/const-generics/generic_const_exprs/typeid-equality-by-subtyping.stderr b/tests/ui/const-generics/generic_const_exprs/typeid-equality-by-subtyping.stderr index 3bae93ccb83fb..77f93774f978b 100644 --- a/tests/ui/const-generics/generic_const_exprs/typeid-equality-by-subtyping.stderr +++ b/tests/ui/const-generics/generic_const_exprs/typeid-equality-by-subtyping.stderr @@ -7,5 +7,12 @@ LL | WHAT_A_TYPE => 0, = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details -error: aborting due to 1 previous error +error[E0277]: the trait bound `for<'a, 'b> fn(&'a (), &'b ()): WithAssoc` is not satisfied + --> $DIR/typeid-equality-by-subtyping.rs:44:51 + | +LL | fn unsound(x: >::Assoc) -> >::Assoc + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `WithAssoc` is not implemented for `for<'a, 'b> fn(&'a (), &'b ())` + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/higher-ranked/higher-ranked-lifetime-equality.rs b/tests/ui/higher-ranked/higher-ranked-lifetime-equality.rs new file mode 100644 index 0000000000000..cefe83931f2d2 --- /dev/null +++ b/tests/ui/higher-ranked/higher-ranked-lifetime-equality.rs @@ -0,0 +1,36 @@ +type One = for<'a> fn(&'a (), &'a ()); +type Two = for<'a, 'b> fn(&'a (), &'b ()); + +mod my_api { + use std::any::Any; + use std::marker::PhantomData; + + pub struct Foo { + a: &'static dyn Any, + _p: PhantomData<*mut T>, // invariant, the type of the `dyn Any` + } + + impl Foo { + pub fn deref(&self) -> &'static T { + match self.a.downcast_ref::() { + None => unsafe { std::hint::unreachable_unchecked() }, + Some(a) => a, + } + } + + pub fn new(a: T) -> Foo { + Foo:: { a: Box::leak(Box::new(a)), _p: PhantomData } + } + } +} + +use my_api::*; + +fn main() { + let foo = Foo::::new((|_, _| ()) as One); + foo.deref(); + let foo: Foo = foo; + //~^ ERROR mismatched types [E0308] + //~| ERROR mismatched types [E0308] + foo.deref(); +} diff --git a/tests/ui/higher-ranked/higher-ranked-lifetime-equality.stderr b/tests/ui/higher-ranked/higher-ranked-lifetime-equality.stderr new file mode 100644 index 0000000000000..b673539edda44 --- /dev/null +++ b/tests/ui/higher-ranked/higher-ranked-lifetime-equality.stderr @@ -0,0 +1,22 @@ +error[E0308]: mismatched types + --> $DIR/higher-ranked-lifetime-equality.rs:32:25 + | +LL | let foo: Foo = foo; + | ^^^ one type is more general than the other + | + = note: expected struct `my_api::Foo fn(&'a (), &'b ())>` + found struct `my_api::Foo fn(&'a (), &'a ())>` + +error[E0308]: mismatched types + --> $DIR/higher-ranked-lifetime-equality.rs:32:25 + | +LL | let foo: Foo = foo; + | ^^^ one type is more general than the other + | + = note: expected struct `my_api::Foo fn(&'a (), &'b ())>` + found struct `my_api::Foo fn(&'a (), &'a ())>` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-covariant.rs b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-covariant.rs index f95496a6c3cc0..8dcccfc217be1 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-covariant.rs +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-covariant.rs @@ -2,8 +2,6 @@ // // In particular, we test this pattern in trait solving, where it is not connected // to any part of the source code. -// -// check-pass trait Trait {} @@ -34,4 +32,5 @@ fn main() { // This is because we can use `'static`. foo::<()>(); + //~^ ERROR implementation of `Trait` is not general enough } diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-covariant.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-covariant.stderr new file mode 100644 index 0000000000000..893f49ce8f5f0 --- /dev/null +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-covariant.stderr @@ -0,0 +1,11 @@ +error: implementation of `Trait` is not general enough + --> $DIR/hrtb-exists-forall-trait-covariant.rs:34:5 + | +LL | foo::<()>(); + | ^^^^^^^^^^^ implementation of `Trait` is not general enough + | + = note: `()` must implement `Trait fn(fn(&'b u32))>` + = note: ...but it actually implements `Trait`, for some specific lifetime `'0` + +error: aborting due to 1 previous error + diff --git a/tests/ui/lub-glb/old-lub-glb-hr-eq.rs b/tests/ui/lub-glb/old-lub-glb-hr-eq.rs index fbf4aee02045d..df288793608d8 100644 --- a/tests/ui/lub-glb/old-lub-glb-hr-eq.rs +++ b/tests/ui/lub-glb/old-lub-glb-hr-eq.rs @@ -3,8 +3,6 @@ // error. However, now that we handle subtyping correctly, we no // longer get an error, because we recognize these two types as // equivalent! -// -// check-pass fn foo(x: fn(&u8, &u8), y: for<'a> fn(&'a u8, &'a u8)) { // The two types above are actually equivalent. With the older @@ -13,6 +11,7 @@ fn foo(x: fn(&u8, &u8), y: for<'a> fn(&'a u8, &'a u8)) { let z = match 22 { 0 => x, _ => y, + //~^ ERROR `match` arms have incompatible types [E0308] }; } diff --git a/tests/ui/lub-glb/old-lub-glb-hr-eq.stderr b/tests/ui/lub-glb/old-lub-glb-hr-eq.stderr new file mode 100644 index 0000000000000..e7c73a15d508b --- /dev/null +++ b/tests/ui/lub-glb/old-lub-glb-hr-eq.stderr @@ -0,0 +1,19 @@ +error[E0308]: `match` arms have incompatible types + --> $DIR/old-lub-glb-hr-eq.rs:13:14 + | +LL | let z = match 22 { + | _____________- +LL | | 0 => x, + | | - this is found to be of type `for<'a, 'b> fn(&'a u8, &'b u8)` +LL | | _ => y, + | | ^ one type is more general than the other +LL | | +LL | | }; + | |_____- `match` arms have incompatible types + | + = note: expected fn pointer `for<'a, 'b> fn(&'a u8, &'b u8)` + found fn pointer `for<'a> fn(&'a u8, &'a u8)` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/nll/relate_tys/hr-fn-aau-eq-abu.rs b/tests/ui/nll/relate_tys/hr-fn-aau-eq-abu.rs index 92730341c1110..4a650c137a1ba 100644 --- a/tests/ui/nll/relate_tys/hr-fn-aau-eq-abu.rs +++ b/tests/ui/nll/relate_tys/hr-fn-aau-eq-abu.rs @@ -6,7 +6,6 @@ // another -- effectively, the single lifetime `'a` is just inferred // to be the intersection of the two distinct lifetimes. // -// check-pass // compile-flags:-Zno-leak-check use std::cell::Cell; @@ -17,7 +16,9 @@ fn make_cell_aa() -> Cell fn(&'a u32, &'a u32)> { fn aa_eq_ab() { let a: Cell fn(&'a u32, &'b u32)> = make_cell_aa(); + //~^ ERROR mismatched types [E0308] + //~| ERROR mismatched types [E0308] drop(a); } -fn main() { } +fn main() {} diff --git a/tests/ui/nll/relate_tys/hr-fn-aau-eq-abu.stderr b/tests/ui/nll/relate_tys/hr-fn-aau-eq-abu.stderr new file mode 100644 index 0000000000000..7794a2cf49646 --- /dev/null +++ b/tests/ui/nll/relate_tys/hr-fn-aau-eq-abu.stderr @@ -0,0 +1,22 @@ +error[E0308]: mismatched types + --> $DIR/hr-fn-aau-eq-abu.rs:18:53 + | +LL | let a: Cell fn(&'a u32, &'b u32)> = make_cell_aa(); + | ^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected struct `Cell fn(&'a u32, &'b u32)>` + found struct `Cell fn(&'a u32, &'a u32)>` + +error[E0308]: mismatched types + --> $DIR/hr-fn-aau-eq-abu.rs:18:53 + | +LL | let a: Cell fn(&'a u32, &'b u32)> = make_cell_aa(); + | ^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected struct `Cell fn(&'a u32, &'b u32)>` + found struct `Cell fn(&'a u32, &'a u32)>` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/traits/new-solver/member-constraints-in-root-universe.rs b/tests/ui/traits/new-solver/member-constraints-in-root-universe.rs index 97c4430586447..39d58dab97b7d 100644 --- a/tests/ui/traits/new-solver/member-constraints-in-root-universe.rs +++ b/tests/ui/traits/new-solver/member-constraints-in-root-universe.rs @@ -1,5 +1,4 @@ // compile-flags: -Ztrait-solver=next -// check-pass trait Trait { type Ty; @@ -11,6 +10,8 @@ impl Trait for for<'a> fn(&'a u8, &'a u8) { // argument is necessary to create universes before registering the hidden type. fn test<'a>(_: ::Ty) -> impl Sized { + //~^ ERROR the type ` fn(&'a u8, &'b u8) as Trait>::Ty` is not well-formed + //~| ERROR the size for values of type ` fn(&'a u8, &'b u8) as Trait>::Ty` cannot be known at compilation time [E0277] "hidden type is `&'?0 str` with '?0 member of ['static,]" } diff --git a/tests/ui/traits/new-solver/member-constraints-in-root-universe.stderr b/tests/ui/traits/new-solver/member-constraints-in-root-universe.stderr new file mode 100644 index 0000000000000..06f96c85df527 --- /dev/null +++ b/tests/ui/traits/new-solver/member-constraints-in-root-universe.stderr @@ -0,0 +1,22 @@ +error: the type ` fn(&'a u8, &'b u8) as Trait>::Ty` is not well-formed + --> $DIR/member-constraints-in-root-universe.rs:12:16 + | +LL | fn test<'a>(_: ::Ty) -> impl Sized { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: the size for values of type ` fn(&'a u8, &'b u8) as Trait>::Ty` cannot be known at compilation time + --> $DIR/member-constraints-in-root-universe.rs:12:13 + | +LL | fn test<'a>(_: ::Ty) -> impl Sized { + | ^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for ` fn(&'a u8, &'b u8) as Trait>::Ty` + = help: unsized fn params are gated as an unstable feature +help: function arguments must have a statically known size, borrowed types always have a known size + | +LL | fn test<'a>(_: &::Ty) -> impl Sized { + | + + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`.