diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 1e5fea1db9fcc..857e4f66489ab 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -35,13 +35,13 @@ //! // 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::{Applicability, Diag, struct_span_code_err}; -use rustc_hir as hir; use rustc_hir::attrs::InlineAttr; use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::{self as hir, LangItem}; use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer; use rustc_infer::infer::relate::RelateResult; 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_span::{BytePos, DUMMY_SP, DesugaringKind, Span}; 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::{ self, ImplSource, NormalizeExt, ObligationCause, ObligationCauseCode, ObligationCtxt, @@ -639,11 +641,44 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { Adjust::Pointer(PointerCoercion::Unsize), )?; - let mut selcx = traits::SelectionContext::new(self); - // Create an obligation for `Source: CoerceUnsized`. 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>, 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. // // 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 // allocation, at the (very small) cost of (occasionally) having to // shift subsequent elements down when removing the front element. - let mut queue: SmallVec<[PredicateObligation<'tcx>; 4]> = smallvec![Obligation::new( - self.tcx, - cause, - self.fcx.param_env, - ty::TraitRef::new(self.tcx, coerce_unsized_did, [coerce_source, coerce_target]) - )]; + let mut queue: SmallVec<[PredicateObligation<'tcx>; 4]> = smallvec![obligation]; // Keep resolving `CoerceUnsized` and `Unsize` predicates to avoid // 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 // be silent, as it causes a type mismatch later. } - Ok(Some(ImplSource::UserDefined(impl_source))) => { queue.extend(impl_source.nested); // Certain incoherent `CoerceUnsized` implementations may cause ICEs, @@ -767,7 +796,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { } } - Ok(coercion) + Ok(()) } /// Applies reborrowing for `Pin` @@ -2005,3 +2034,69 @@ impl AsCoercionSite for hir::Arm<'_> { 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(()) + } + } + } + } +} diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs index 367e2b6b372ae..ff37cb75a5c53 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs @@ -6,7 +6,7 @@ use rustc_middle::ty::{self, Ty, TypeVisitableExt}; use rustc_span::Span; use rustc_trait_selection::solve::Certainty; use rustc_trait_selection::solve::inspect::{ - InspectConfig, InspectGoal, ProofTreeInferCtxtExt, ProofTreeVisitor, + InferCtxtProofTreeExt, InspectConfig, InspectGoal, ProofTreeVisitor, }; use tracing::{debug, instrument, trace}; diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index ddd79e1dc9405..7b61a653ae31e 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -24,7 +24,7 @@ use tracing::instrument; use self::derive_errors::*; use super::Certainty; use super::delegate::SolverDelegate; -use super::inspect::{self, ProofTreeInferCtxtExt}; +use super::inspect::{self, InferCtxtProofTreeExt}; use crate::traits::{FulfillmentError, ScrubbedTraitError}; mod derive_errors; diff --git a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs index eef0ddcbf5965..904a0ac45777b 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs @@ -15,7 +15,7 @@ use rustc_next_trait_solver::solve::{GoalEvaluation, SolverDelegateEvalExt as _} use tracing::{instrument, trace}; 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::traits::{FulfillmentError, FulfillmentErrorCode, wf}; diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs index 488315054c6aa..cdbf2b0aeb834 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs @@ -463,7 +463,7 @@ pub trait ProofTreeVisitor<'tcx> { fn visit_goal(&mut self, goal: &InspectGoal<'_, 'tcx>) -> Self::Result; } -#[extension(pub trait ProofTreeInferCtxtExt<'tcx>)] +#[extension(pub trait InferCtxtProofTreeExt<'tcx>)] impl<'tcx> InferCtxt<'tcx> { fn visit_proof_tree>( &self, diff --git a/compiler/rustc_trait_selection/src/solve/select.rs b/compiler/rustc_trait_selection/src/solve/select.rs index d7e7ffd5d28c6..1feaab2404153 100644 --- a/compiler/rustc_trait_selection/src/solve/select.rs +++ b/compiler/rustc_trait_selection/src/solve/select.rs @@ -12,7 +12,7 @@ use rustc_middle::{bug, span_bug}; use rustc_span::Span; use thin_vec::thin_vec; -use crate::solve::inspect::{self, ProofTreeInferCtxtExt}; +use crate::solve::inspect::{self, InferCtxtProofTreeExt}; #[extension(pub trait InferCtxtSelectExt<'tcx>)] impl<'tcx> InferCtxt<'tcx> { diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index e488fb6802f84..1ccda94dc89b2 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -29,7 +29,7 @@ use tracing::{debug, instrument, warn}; use super::ObligationCtxt; use crate::error_reporting::traits::suggest_new_overflow_limit; 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::traits::query::evaluate_obligation::InferCtxtExt; use crate::traits::select::IntercrateAmbiguityCause; diff --git a/tests/ui/dst/dst-object-from-unsized-type.stderr b/tests/ui/dst/dst-object-from-unsized-type.current.stderr similarity index 90% rename from tests/ui/dst/dst-object-from-unsized-type.stderr rename to tests/ui/dst/dst-object-from-unsized-type.current.stderr index cbb7dc5e9f421..be9966743d4ee 100644 --- a/tests/ui/dst/dst-object-from-unsized-type.stderr +++ b/tests/ui/dst/dst-object-from-unsized-type.current.stderr @@ -1,5 +1,5 @@ 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: &T) { | - this type parameter needs to be `Sized` @@ -14,7 +14,7 @@ LL + fn test1(t: &T) { | 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: &T) { | - this type parameter needs to be `Sized` @@ -29,7 +29,7 @@ LL + fn test2(t: &T) { | 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"]; | ^^^^ 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` 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; | ^ doesn't have a size known at compile-time diff --git a/tests/ui/dst/dst-object-from-unsized-type.next.stderr b/tests/ui/dst/dst-object-from-unsized-type.next.stderr new file mode 100644 index 0000000000000..032ba0cb14aeb --- /dev/null +++ b/tests/ui/dst/dst-object-from-unsized-type.next.stderr @@ -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: &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: &T) { +LL + fn test1(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: &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: &T) { +LL + fn test2(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`. diff --git a/tests/ui/dst/dst-object-from-unsized-type.rs b/tests/ui/dst/dst-object-from-unsized-type.rs index 3cd5b1ed6f462..1e6113b3fc6fb 100644 --- a/tests/ui/dst/dst-object-from-unsized-type.rs +++ b/tests/ui/dst/dst-object-from-unsized-type.rs @@ -1,4 +1,7 @@ // 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) {} } impl Foo for str {} @@ -6,22 +9,26 @@ impl Foo for [u8] {} fn test1(t: &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: &T) { 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() { 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]) { 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() { } diff --git a/tests/ui/traits/next-solver/unsize-goal-mismatch-2.next.stderr b/tests/ui/traits/next-solver/unsize-goal-mismatch-2.next.stderr new file mode 100644 index 0000000000000..b415db33addbf --- /dev/null +++ b/tests/ui/traits/next-solver/unsize-goal-mismatch-2.next.stderr @@ -0,0 +1,13 @@ +error[E0283]: type annotations needed: cannot satisfy `dyn Trait<&()>: Unsize>` + --> $DIR/unsize-goal-mismatch-2.rs:15:5 + | +LL | x + | ^ + | + = note: cannot satisfy `dyn Trait<&()>: Unsize>` + = note: required for `Box>` to implement `CoerceUnsized>>` + = 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`. diff --git a/tests/ui/traits/next-solver/unsize-goal-mismatch-2.rs b/tests/ui/traits/next-solver/unsize-goal-mismatch-2.rs new file mode 100644 index 0000000000000..2b174eac5c151 --- /dev/null +++ b/tests/ui/traits/next-solver/unsize-goal-mismatch-2.rs @@ -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 {} +trait Trait: Super + for<'hr> Super<&'hr ()> {} + +fn foo<'a>(x: Box>) -> Box> { + x + //[next]~^ ERROR type annotations needed: cannot satisfy `dyn Trait<&()>: Unsize>` +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/unsize-goal-mismatch.current.stderr b/tests/ui/traits/next-solver/unsize-goal-mismatch.current.stderr new file mode 100644 index 0000000000000..278a68e154714 --- /dev/null +++ b/tests/ui/traits/next-solver/unsize-goal-mismatch.current.stderr @@ -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`. diff --git a/tests/ui/traits/next-solver/unsize-goal-mismatch.next.stderr b/tests/ui/traits/next-solver/unsize-goal-mismatch.next.stderr new file mode 100644 index 0000000000000..cfb978240cbc6 --- /dev/null +++ b/tests/ui/traits/next-solver/unsize-goal-mismatch.next.stderr @@ -0,0 +1,13 @@ +error[E0283]: type annotations needed: cannot satisfy `dyn Trait<'_>: Unsize>` + --> $DIR/unsize-goal-mismatch.rs:15:5 + | +LL | x + | ^ + | + = note: cannot satisfy `dyn Trait<'_>: Unsize>` + = note: required for `Box>` to implement `CoerceUnsized>>` + = 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`. diff --git a/tests/ui/traits/next-solver/unsize-goal-mismatch.rs b/tests/ui/traits/next-solver/unsize-goal-mismatch.rs new file mode 100644 index 0000000000000..f57cceb4096a0 --- /dev/null +++ b/tests/ui/traits/next-solver/unsize-goal-mismatch.rs @@ -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>) -> Box> { + x + //[next]~^ ERROR type annotations needed: cannot satisfy `dyn Trait<'_>: Unsize> +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/unsize-overflow.rs b/tests/ui/traits/next-solver/unsize-overflow.rs new file mode 100644 index 0000000000000..036be02aaeae3 --- /dev/null +++ b/tests/ui/traits/next-solver/unsize-overflow.rs @@ -0,0 +1,7 @@ +//@ compile-flags: -Znext-solver +#![recursion_limit = "8"] + +fn main() { + let _: Box = Box::new(&&&&&&&1); + //~^ ERROR overflow evaluating the requirement `Box<&&&&&&&i32>: CoerceUnsized> +} diff --git a/tests/ui/traits/next-solver/unsize-overflow.stderr b/tests/ui/traits/next-solver/unsize-overflow.stderr new file mode 100644 index 0000000000000..ae0f2957243c7 --- /dev/null +++ b/tests/ui/traits/next-solver/unsize-overflow.stderr @@ -0,0 +1,12 @@ +error[E0275]: overflow evaluating the requirement `Box<&&&&&&&i32>: CoerceUnsized>` + --> $DIR/unsize-overflow.rs:5:28 + | +LL | let _: Box = 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` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/trait-upcasting/higher-ranked-upcasting-ub.next.stderr b/tests/ui/traits/trait-upcasting/higher-ranked-upcasting-ub.next.stderr index b82f1eef42b5a..392680aa50643 100644 --- a/tests/ui/traits/trait-upcasting/higher-ranked-upcasting-ub.next.stderr +++ b/tests/ui/traits/trait-upcasting/higher-ranked-upcasting-ub.next.stderr @@ -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 | -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 - | ^ expected trait `Supertrait`, found trait `Subtrait` + | ^ the trait `Unsize Supertrait<'a, 'b>>` is not implemented for `dyn for<'a> Subtrait<'a, 'a>` | - = note: expected reference `&dyn for<'a, 'b> Supertrait<'a, 'b>` - found reference `&dyn for<'a> Subtrait<'a, 'a>` + = note: all implementations of `Unsize` are provided automatically by the compiler, see for more information + = 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 -For more information about this error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/trait-upcasting/higher-ranked-upcasting-ub.rs b/tests/ui/traits/trait-upcasting/higher-ranked-upcasting-ub.rs index af2594b95f3d2..98ca30ca391f7 100644 --- a/tests/ui/traits/trait-upcasting/higher-ranked-upcasting-ub.rs +++ b/tests/ui/traits/trait-upcasting/higher-ranked-upcasting-ub.rs @@ -19,8 +19,10 @@ impl<'a> Supertrait<'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> { - x //~ ERROR mismatched types + x //[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 {