Rollup merge of #147840 - jdonszelmann:unsizing-coercions, r=lcnr

Rework unsizing coercions in the new solver

Replaces https://github.com/rust-lang/rust/pull/141926, contains:

- a commit adding tests that fail before this work
- the two commits from the previous PR
- a commit in which these tests are fixed
- finally, a fixup for an in my opinion rather large regression in diagnostics. It's still not perfect, but better?

I hope this is roughly what you had in mind

Fixes https://github.com/rust-lang/trait-system-refactor-initiative/issues/241 and https://github.com/rust-lang/trait-system-refactor-initiative/issues/238, adding tests for both

r? ````@lcnr````
This commit is contained in:
Stuart Cook
2025-10-28 20:39:33 +11:00
committed by GitHub
19 changed files with 294 additions and 34 deletions

View File

@@ -35,13 +35,13 @@
//! // and are then unable to coerce `&7i32` to `&mut i32`. //! // and are then unable to coerce `&7i32` to `&mut i32`.
//! ``` //! ```
use std::ops::Deref; use std::ops::{ControlFlow, Deref};
use rustc_errors::codes::*; use rustc_errors::codes::*;
use rustc_errors::{Applicability, Diag, struct_span_code_err}; use rustc_errors::{Applicability, Diag, struct_span_code_err};
use rustc_hir as hir;
use rustc_hir::attrs::InlineAttr; use rustc_hir::attrs::InlineAttr;
use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::{self as hir, LangItem};
use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer; use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
use rustc_infer::infer::relate::RelateResult; use rustc_infer::infer::relate::RelateResult;
use rustc_infer::infer::{DefineOpaqueTypes, InferOk, InferResult, RegionVariableOrigin}; use rustc_infer::infer::{DefineOpaqueTypes, InferOk, InferResult, RegionVariableOrigin};
@@ -56,6 +56,8 @@ use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt}; use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt};
use rustc_span::{BytePos, DUMMY_SP, DesugaringKind, Span}; use rustc_span::{BytePos, DUMMY_SP, DesugaringKind, Span};
use rustc_trait_selection::infer::InferCtxtExt as _; use rustc_trait_selection::infer::InferCtxtExt as _;
use rustc_trait_selection::solve::inspect::{self, InferCtxtProofTreeExt, ProofTreeVisitor};
use rustc_trait_selection::solve::{Certainty, Goal, NoSolution};
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
use rustc_trait_selection::traits::{ use rustc_trait_selection::traits::{
self, ImplSource, NormalizeExt, ObligationCause, ObligationCauseCode, ObligationCtxt, self, ImplSource, NormalizeExt, ObligationCause, ObligationCauseCode, ObligationCtxt,
@@ -639,11 +641,44 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
Adjust::Pointer(PointerCoercion::Unsize), Adjust::Pointer(PointerCoercion::Unsize),
)?; )?;
let mut selcx = traits::SelectionContext::new(self);
// Create an obligation for `Source: CoerceUnsized<Target>`. // Create an obligation for `Source: CoerceUnsized<Target>`.
let cause = self.cause(self.cause.span, ObligationCauseCode::Coercion { source, target }); let cause = self.cause(self.cause.span, ObligationCauseCode::Coercion { source, target });
let pred = ty::TraitRef::new(self.tcx, coerce_unsized_did, [coerce_source, coerce_target]);
let obligation = Obligation::new(self.tcx, cause, self.fcx.param_env, pred);
if self.next_trait_solver() {
coercion.obligations.push(obligation);
if self
.infcx
.visit_proof_tree(
Goal::new(self.tcx, self.param_env, pred),
&mut CoerceVisitor { fcx: self.fcx, span: self.cause.span },
)
.is_break()
{
return Err(TypeError::Mismatch);
}
} else {
self.coerce_unsized_old_solver(
obligation,
&mut coercion,
coerce_unsized_did,
unsize_did,
)?;
}
Ok(coercion)
}
fn coerce_unsized_old_solver(
&self,
obligation: Obligation<'tcx, ty::Predicate<'tcx>>,
coercion: &mut InferOk<'tcx, (Vec<Adjustment<'tcx>>, Ty<'tcx>)>,
coerce_unsized_did: DefId,
unsize_did: DefId,
) -> Result<(), TypeError<'tcx>> {
let mut selcx = traits::SelectionContext::new(self);
// Use a FIFO queue for this custom fulfillment procedure. // Use a FIFO queue for this custom fulfillment procedure.
// //
// A Vec (or SmallVec) is not a natural choice for a queue. However, // A Vec (or SmallVec) is not a natural choice for a queue. However,
@@ -651,12 +686,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
// and almost never more than 3. By using a SmallVec we avoid an // and almost never more than 3. By using a SmallVec we avoid an
// allocation, at the (very small) cost of (occasionally) having to // allocation, at the (very small) cost of (occasionally) having to
// shift subsequent elements down when removing the front element. // shift subsequent elements down when removing the front element.
let mut queue: SmallVec<[PredicateObligation<'tcx>; 4]> = smallvec![Obligation::new( let mut queue: SmallVec<[PredicateObligation<'tcx>; 4]> = smallvec![obligation];
self.tcx,
cause,
self.fcx.param_env,
ty::TraitRef::new(self.tcx, coerce_unsized_did, [coerce_source, coerce_target])
)];
// Keep resolving `CoerceUnsized` and `Unsize` predicates to avoid // Keep resolving `CoerceUnsized` and `Unsize` predicates to avoid
// emitting a coercion in cases like `Foo<$1>` -> `Foo<$2>`, where // emitting a coercion in cases like `Foo<$1>` -> `Foo<$2>`, where
@@ -749,7 +779,6 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
// with the unsizing - the lack of a coercion should // with the unsizing - the lack of a coercion should
// be silent, as it causes a type mismatch later. // be silent, as it causes a type mismatch later.
} }
Ok(Some(ImplSource::UserDefined(impl_source))) => { Ok(Some(ImplSource::UserDefined(impl_source))) => {
queue.extend(impl_source.nested); queue.extend(impl_source.nested);
// Certain incoherent `CoerceUnsized` implementations may cause ICEs, // Certain incoherent `CoerceUnsized` implementations may cause ICEs,
@@ -767,7 +796,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
} }
} }
Ok(coercion) Ok(())
} }
/// Applies reborrowing for `Pin` /// Applies reborrowing for `Pin`
@@ -2005,3 +2034,69 @@ impl AsCoercionSite for hir::Arm<'_> {
self.body self.body
} }
} }
/// Recursively visit goals to decide whether an unsizing is possible.
/// `Break`s when it isn't, and an error should be raised.
/// `Continue`s when an unsizing ok based on an implementation of the `Unsize` trait / lang item.
struct CoerceVisitor<'a, 'tcx> {
fcx: &'a FnCtxt<'a, 'tcx>,
span: Span,
}
impl<'tcx> ProofTreeVisitor<'tcx> for CoerceVisitor<'_, 'tcx> {
type Result = ControlFlow<()>;
fn span(&self) -> Span {
self.span
}
fn visit_goal(&mut self, goal: &inspect::InspectGoal<'_, 'tcx>) -> Self::Result {
let Some(pred) = goal.goal().predicate.as_trait_clause() else {
return ControlFlow::Continue(());
};
// Make sure this predicate is referring to either an `Unsize` or `CoerceUnsized` trait,
// Otherwise there's nothing to do.
if !self.fcx.tcx.is_lang_item(pred.def_id(), LangItem::Unsize)
&& !self.fcx.tcx.is_lang_item(pred.def_id(), LangItem::CoerceUnsized)
{
return ControlFlow::Continue(());
}
match goal.result() {
// If we prove the `Unsize` or `CoerceUnsized` goal, continue recursing.
Ok(Certainty::Yes) => ControlFlow::Continue(()),
Err(NoSolution) => {
// Even if we find no solution, continue recursing if we find a single candidate
// for which we're shallowly certain it holds to get the right error source.
if let [only_candidate] = &goal.candidates()[..]
&& only_candidate.shallow_certainty() == Certainty::Yes
{
only_candidate.visit_nested_no_probe(self)
} else {
ControlFlow::Break(())
}
}
Ok(Certainty::Maybe { .. }) => {
// FIXME: structurally normalize?
if self.fcx.tcx.is_lang_item(pred.def_id(), LangItem::Unsize)
&& let ty::Dynamic(..) = pred.skip_binder().trait_ref.args.type_at(1).kind()
&& let ty::Infer(ty::TyVar(vid)) = *pred.self_ty().skip_binder().kind()
&& self.fcx.type_var_is_sized(vid)
{
// We get here when trying to unsize a type variable to a `dyn Trait`,
// knowing that that variable is sized. Unsizing definitely has to happen in that case.
// If the variable weren't sized, we may not need an unsizing coercion.
// In general, we don't want to add coercions too eagerly since it makes error messages much worse.
ControlFlow::Continue(())
} else if let Some(cand) = goal.unique_applicable_candidate()
&& cand.shallow_certainty() == Certainty::Yes
{
cand.visit_nested_no_probe(self)
} else {
ControlFlow::Break(())
}
}
}
}
}

View File

@@ -5,7 +5,7 @@ use rustc_middle::ty::{self, Ty, TypeVisitableExt};
use rustc_span::Span; use rustc_span::Span;
use rustc_trait_selection::solve::Certainty; use rustc_trait_selection::solve::Certainty;
use rustc_trait_selection::solve::inspect::{ use rustc_trait_selection::solve::inspect::{
InspectConfig, InspectGoal, ProofTreeInferCtxtExt, ProofTreeVisitor, InferCtxtProofTreeExt, InspectConfig, InspectGoal, ProofTreeVisitor,
}; };
use tracing::{debug, instrument, trace}; use tracing::{debug, instrument, trace};

View File

@@ -24,7 +24,7 @@ use tracing::instrument;
use self::derive_errors::*; use self::derive_errors::*;
use super::Certainty; use super::Certainty;
use super::delegate::SolverDelegate; use super::delegate::SolverDelegate;
use super::inspect::{self, ProofTreeInferCtxtExt}; use super::inspect::{self, InferCtxtProofTreeExt};
use crate::traits::{FulfillmentError, ScrubbedTraitError}; use crate::traits::{FulfillmentError, ScrubbedTraitError};
mod derive_errors; mod derive_errors;

View File

@@ -15,7 +15,7 @@ use rustc_next_trait_solver::solve::{GoalEvaluation, SolverDelegateEvalExt as _}
use tracing::{instrument, trace}; use tracing::{instrument, trace};
use crate::solve::delegate::SolverDelegate; use crate::solve::delegate::SolverDelegate;
use crate::solve::inspect::{self, ProofTreeInferCtxtExt, ProofTreeVisitor}; use crate::solve::inspect::{self, InferCtxtProofTreeExt, ProofTreeVisitor};
use crate::solve::{Certainty, deeply_normalize_for_diagnostics}; use crate::solve::{Certainty, deeply_normalize_for_diagnostics};
use crate::traits::{FulfillmentError, FulfillmentErrorCode, wf}; use crate::traits::{FulfillmentError, FulfillmentErrorCode, wf};

View File

@@ -463,7 +463,7 @@ pub trait ProofTreeVisitor<'tcx> {
fn visit_goal(&mut self, goal: &InspectGoal<'_, 'tcx>) -> Self::Result; fn visit_goal(&mut self, goal: &InspectGoal<'_, 'tcx>) -> Self::Result;
} }
#[extension(pub trait ProofTreeInferCtxtExt<'tcx>)] #[extension(pub trait InferCtxtProofTreeExt<'tcx>)]
impl<'tcx> InferCtxt<'tcx> { impl<'tcx> InferCtxt<'tcx> {
fn visit_proof_tree<V: ProofTreeVisitor<'tcx>>( fn visit_proof_tree<V: ProofTreeVisitor<'tcx>>(
&self, &self,

View File

@@ -12,7 +12,7 @@ use rustc_middle::{bug, span_bug};
use rustc_span::Span; use rustc_span::Span;
use thin_vec::thin_vec; use thin_vec::thin_vec;
use crate::solve::inspect::{self, ProofTreeInferCtxtExt}; use crate::solve::inspect::{self, InferCtxtProofTreeExt};
#[extension(pub trait InferCtxtSelectExt<'tcx>)] #[extension(pub trait InferCtxtSelectExt<'tcx>)]
impl<'tcx> InferCtxt<'tcx> { impl<'tcx> InferCtxt<'tcx> {

View File

@@ -29,7 +29,7 @@ use tracing::{debug, instrument, warn};
use super::ObligationCtxt; use super::ObligationCtxt;
use crate::error_reporting::traits::suggest_new_overflow_limit; use crate::error_reporting::traits::suggest_new_overflow_limit;
use crate::infer::InferOk; use crate::infer::InferOk;
use crate::solve::inspect::{InspectGoal, ProofTreeInferCtxtExt, ProofTreeVisitor}; use crate::solve::inspect::{InferCtxtProofTreeExt, InspectGoal, ProofTreeVisitor};
use crate::solve::{SolverDelegate, deeply_normalize_for_diagnostics, inspect}; use crate::solve::{SolverDelegate, deeply_normalize_for_diagnostics, inspect};
use crate::traits::query::evaluate_obligation::InferCtxtExt; use crate::traits::query::evaluate_obligation::InferCtxtExt;
use crate::traits::select::IntercrateAmbiguityCause; use crate::traits::select::IntercrateAmbiguityCause;

View File

@@ -1,5 +1,5 @@
error[E0277]: the size for values of type `T` cannot be known at compilation time error[E0277]: the size for values of type `T` cannot be known at compilation time
--> $DIR/dst-object-from-unsized-type.rs:8:23 --> $DIR/dst-object-from-unsized-type.rs:11:23
| |
LL | fn test1<T: ?Sized + Foo>(t: &T) { LL | fn test1<T: ?Sized + Foo>(t: &T) {
| - this type parameter needs to be `Sized` | - this type parameter needs to be `Sized`
@@ -14,7 +14,7 @@ LL + fn test1<T: Foo>(t: &T) {
| |
error[E0277]: the size for values of type `T` cannot be known at compilation time error[E0277]: the size for values of type `T` cannot be known at compilation time
--> $DIR/dst-object-from-unsized-type.rs:13:23 --> $DIR/dst-object-from-unsized-type.rs:17:23
| |
LL | fn test2<T: ?Sized + Foo>(t: &T) { LL | fn test2<T: ?Sized + Foo>(t: &T) {
| - this type parameter needs to be `Sized` | - this type parameter needs to be `Sized`
@@ -29,7 +29,7 @@ LL + fn test2<T: Foo>(t: &T) {
| |
error[E0277]: the size for values of type `str` cannot be known at compilation time error[E0277]: the size for values of type `str` cannot be known at compilation time
--> $DIR/dst-object-from-unsized-type.rs:18:28 --> $DIR/dst-object-from-unsized-type.rs:23:28
| |
LL | let _: &[&dyn Foo] = &["hi"]; LL | let _: &[&dyn Foo] = &["hi"];
| ^^^^ doesn't have a size known at compile-time | ^^^^ doesn't have a size known at compile-time
@@ -38,7 +38,7 @@ LL | let _: &[&dyn Foo] = &["hi"];
= note: required for the cast from `&'static str` to `&dyn Foo` = note: required for the cast from `&'static str` to `&dyn Foo`
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
--> $DIR/dst-object-from-unsized-type.rs:23:23 --> $DIR/dst-object-from-unsized-type.rs:29:23
| |
LL | let _: &dyn Foo = x as &dyn Foo; LL | let _: &dyn Foo = x as &dyn Foo;
| ^ doesn't have a size known at compile-time | ^ doesn't have a size known at compile-time

View File

@@ -0,0 +1,57 @@
error[E0277]: the trait bound `&T: CoerceUnsized<&dyn Foo>` is not satisfied in `T`
--> $DIR/dst-object-from-unsized-type.rs:11:23
|
LL | fn test1<T: ?Sized + Foo>(t: &T) {
| - this type parameter needs to be `Sized`
LL | let u: &dyn Foo = t;
| ^ within `T`, the trait `Sized` is not implemented for `T`
|
= note: required because it appears within the type `T`
= note: required for `&T` to implement `CoerceUnsized<&dyn Foo>`
= note: required for the cast from `&T` to `&dyn Foo`
help: consider removing the `?Sized` bound to make the type parameter `Sized`
|
LL - fn test1<T: ?Sized + Foo>(t: &T) {
LL + fn test1<T: Foo>(t: &T) {
|
error[E0277]: the trait bound `&T: CoerceUnsized<&dyn Foo>` is not satisfied in `T`
--> $DIR/dst-object-from-unsized-type.rs:17:23
|
LL | fn test2<T: ?Sized + Foo>(t: &T) {
| - this type parameter needs to be `Sized`
LL | let v: &dyn Foo = t as &dyn Foo;
| ^ within `T`, the trait `Sized` is not implemented for `T`
|
= note: required because it appears within the type `T`
= note: required for `&T` to implement `CoerceUnsized<&dyn Foo>`
= note: required for the cast from `&T` to `&dyn Foo`
help: consider removing the `?Sized` bound to make the type parameter `Sized`
|
LL - fn test2<T: ?Sized + Foo>(t: &T) {
LL + fn test2<T: Foo>(t: &T) {
|
error[E0277]: the trait bound `&str: CoerceUnsized<&dyn Foo>` is not satisfied in `str`
--> $DIR/dst-object-from-unsized-type.rs:23:28
|
LL | let _: &[&dyn Foo] = &["hi"];
| ^^^^ within `str`, the trait `Sized` is not implemented for `str`
|
= note: `str` is considered to contain a `[u8]` slice for auto trait purposes
= note: required for `&str` to implement `CoerceUnsized<&dyn Foo>`
= note: required for the cast from `&'static str` to `&dyn Foo`
error[E0277]: the trait bound `&[u8]: CoerceUnsized<&dyn Foo>` is not satisfied in `[u8]`
--> $DIR/dst-object-from-unsized-type.rs:29:23
|
LL | let _: &dyn Foo = x as &dyn Foo;
| ^ within `[u8]`, the trait `Sized` is not implemented for `[u8]`
|
= note: required because it appears within the type `[u8]`
= note: required for `&[u8]` to implement `CoerceUnsized<&dyn Foo>`
= note: required for the cast from `&[u8]` to `&dyn Foo`
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0277`.

View File

@@ -1,4 +1,7 @@
// Test that we cannot create objects from unsized types. // Test that we cannot create objects from unsized types.
//@ revisions: current next
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver
trait Foo { fn foo(&self) {} } trait Foo { fn foo(&self) {} }
impl Foo for str {} impl Foo for str {}
@@ -6,22 +9,26 @@ impl Foo for [u8] {}
fn test1<T: ?Sized + Foo>(t: &T) { fn test1<T: ?Sized + Foo>(t: &T) {
let u: &dyn Foo = t; let u: &dyn Foo = t;
//~^ ERROR the size for values of type //[current]~^ ERROR the size for values of type
//[next]~^^ ERROR the trait bound `&T: CoerceUnsized<&dyn Foo>` is not satisfied in `T`
} }
fn test2<T: ?Sized + Foo>(t: &T) { fn test2<T: ?Sized + Foo>(t: &T) {
let v: &dyn Foo = t as &dyn Foo; let v: &dyn Foo = t as &dyn Foo;
//~^ ERROR the size for values of type //[current]~^ ERROR the size for values of type
//[next]~^^ ERROR the trait bound `&T: CoerceUnsized<&dyn Foo>` is not satisfied in `T`
} }
fn test3() { fn test3() {
let _: &[&dyn Foo] = &["hi"]; let _: &[&dyn Foo] = &["hi"];
//~^ ERROR the size for values of type //[current]~^ ERROR the size for values of type
//[next]~^^ ERROR the trait bound `&str: CoerceUnsized<&dyn Foo>` is not satisfied in `str`
} }
fn test4(x: &[u8]) { fn test4(x: &[u8]) {
let _: &dyn Foo = x as &dyn Foo; let _: &dyn Foo = x as &dyn Foo;
//~^ ERROR the size for values of type //[current]~^ ERROR the size for values of type
//[next]~^^ ERROR the trait bound `&[u8]: CoerceUnsized<&dyn Foo>` is not satisfied in `[u8]`
} }
fn main() { } fn main() { }

View File

@@ -0,0 +1,13 @@
error[E0283]: type annotations needed: cannot satisfy `dyn Trait<&()>: Unsize<dyn Super<&()>>`
--> $DIR/unsize-goal-mismatch-2.rs:15:5
|
LL | x
| ^
|
= note: cannot satisfy `dyn Trait<&()>: Unsize<dyn Super<&()>>`
= note: required for `Box<dyn Trait<&()>>` to implement `CoerceUnsized<Box<dyn Super<&()>>>`
= note: required for the cast from `Box<(dyn Trait<&'a ()> + 'static)>` to `Box<(dyn Super<&'a ()> + 'static)>`
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0283`.

View File

@@ -0,0 +1,19 @@
//@ revisions: current next
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver
//@[current] check-pass
// Test from trait-system-refactor-initiative#241:
// Used to ICE in mir typeck because of ambiguity in the new solver.
// The wrong (first) trait bound was selected.
// This is fixed with new logic for unsizing coercions
// that's independent from that of the old solver, which this test verifies.
trait Super<T> {}
trait Trait<T>: Super<T> + for<'hr> Super<&'hr ()> {}
fn foo<'a>(x: Box<dyn Trait<&'a ()>>) -> Box<dyn Super<&'a ()>> {
x
//[next]~^ ERROR type annotations needed: cannot satisfy `dyn Trait<&()>: Unsize<dyn Super<&()>>`
}
fn main() {}

View File

@@ -0,0 +1,17 @@
error[E0283]: type annotations needed: cannot satisfy `Self: Super<'a>`
--> $DIR/unsize-goal-mismatch.rs:11:18
|
LL | trait Trait<'a>: Super<'a> + for<'hr> Super<'hr> {}
| ^^^^^^^^^
|
note: multiple `impl`s or `where` clauses satisfying `Self: Super<'a>` found
--> $DIR/unsize-goal-mismatch.rs:10:1
|
LL | trait Super<'a> {}
| ^^^^^^^^^^^^^^^
LL | trait Trait<'a>: Super<'a> + for<'hr> Super<'hr> {}
| ^^^^^^^^^^^^^^^^^^^
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0283`.

View File

@@ -0,0 +1,13 @@
error[E0283]: type annotations needed: cannot satisfy `dyn Trait<'_>: Unsize<dyn Super<'_>>`
--> $DIR/unsize-goal-mismatch.rs:15:5
|
LL | x
| ^
|
= note: cannot satisfy `dyn Trait<'_>: Unsize<dyn Super<'_>>`
= note: required for `Box<dyn Trait<'_>>` to implement `CoerceUnsized<Box<dyn Super<'_>>>`
= note: required for the cast from `Box<(dyn Trait<'a> + 'static)>` to `Box<(dyn Super<'a> + 'static)>`
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0283`.

View File

@@ -0,0 +1,19 @@
//@ revisions: current next
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver
// Test from trait-system-refactor-initiative#241:
// Used to ICE in mir typeck because of ambiguity in the new solver.
// The wrong (first) trait bound was selected.
// This is fixed with new logic for unsizing coercions
// that's independent from that of the old solver, which this test verifies.
trait Super<'a> {}
trait Trait<'a>: Super<'a> + for<'hr> Super<'hr> {}
//[current]~^ ERROR type annotations needed: cannot satisfy `Self: Super<'a>`
fn foo<'a>(x: Box<dyn Trait<'a>>) -> Box<dyn Super<'a>> {
x
//[next]~^ ERROR type annotations needed: cannot satisfy `dyn Trait<'_>: Unsize<dyn Super<'_>>
}
fn main() {}

View File

@@ -0,0 +1,7 @@
//@ compile-flags: -Znext-solver
#![recursion_limit = "8"]
fn main() {
let _: Box<dyn Send> = Box::new(&&&&&&&1);
//~^ ERROR overflow evaluating the requirement `Box<&&&&&&&i32>: CoerceUnsized<Box<dyn Send>>
}

View File

@@ -0,0 +1,12 @@
error[E0275]: overflow evaluating the requirement `Box<&&&&&&&i32>: CoerceUnsized<Box<dyn Send>>`
--> $DIR/unsize-overflow.rs:5:28
|
LL | let _: Box<dyn Send> = Box::new(&&&&&&&1);
| ^^^^^^^^^^^^^^^^^^
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "16"]` attribute to your crate (`unsize_overflow`)
= note: required for the cast from `Box<&&&&&&&i32>` to `Box<dyn Send>`
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0275`.

View File

@@ -1,14 +1,13 @@
error[E0308]: mismatched types error[E0277]: the trait bound `&dyn for<'a> Subtrait<'a, 'a>: CoerceUnsized<&dyn for<'a, 'b> Supertrait<'a, 'b>>` is not satisfied
--> $DIR/higher-ranked-upcasting-ub.rs:22:5 --> $DIR/higher-ranked-upcasting-ub.rs:22:5
| |
LL | fn unsound(x: &dyn for<'a> Subtrait<'a, 'a>) -> &dyn for<'a, 'b> Supertrait<'a, 'b> {
| ----------------------------------- expected `&dyn for<'a, 'b> Supertrait<'a, 'b>` because of return type
LL | x LL | x
| ^ expected trait `Supertrait`, found trait `Subtrait` | ^ the trait `Unsize<dyn for<'a, 'b> Supertrait<'a, 'b>>` is not implemented for `dyn for<'a> Subtrait<'a, 'a>`
| |
= note: expected reference `&dyn for<'a, 'b> Supertrait<'a, 'b>` = note: all implementations of `Unsize` are provided automatically by the compiler, see <https://doc.rust-lang.org/stable/std/marker/trait.Unsize.html> for more information
found reference `&dyn for<'a> Subtrait<'a, 'a>` = note: required for `&dyn for<'a> Subtrait<'a, 'a>` to implement `CoerceUnsized<&dyn for<'a, 'b> Supertrait<'a, 'b>>`
= note: required for the cast from `&dyn for<'a> Subtrait<'a, 'a>` to `&dyn for<'a, 'b> Supertrait<'a, 'b>`
error: aborting due to 1 previous error error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0308`. For more information about this error, try `rustc --explain E0277`.

View File

@@ -19,8 +19,10 @@ impl<'a> Supertrait<'a, 'a> for () {
} }
impl<'a> Subtrait<'a, 'a> for () {} impl<'a> Subtrait<'a, 'a> for () {}
fn unsound(x: &dyn for<'a> Subtrait<'a, 'a>) -> &dyn for<'a, 'b> Supertrait<'a, 'b> { fn unsound(x: &dyn for<'a> Subtrait<'a, 'a>) -> &dyn for<'a, 'b> Supertrait<'a, 'b> {
x //~ ERROR mismatched types x
//[current]~^ ERROR mismatched types //[current]~^ ERROR mismatched types
//[current]~| ERROR mismatched types
//[next]~^^^ ERROR the trait bound `&dyn for<'a> Subtrait<'a, 'a>: CoerceUnsized<&dyn for<'a, 'b> Supertrait<'a, 'b>>` is not satisfied
} }
fn transmute<'a, 'b>(x: &'a str) -> &'b str { fn transmute<'a, 'b>(x: &'a str) -> &'b str {