From 628a8585c4a68d0c8d31fda09e337e2d3b61c598 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 17 Mar 2025 10:02:27 +0000 Subject: [PATCH] Remove hacky inference hint in unsizing --- compiler/rustc_hir_typeck/src/coercion.rs | 27 +--- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 12 -- ...erce-issue-49593-box-never.fallback.stderr | 117 +++++++++++++++++ ...ce-issue-49593-box-never.nofallback.stderr | 118 ++++++++++++++++-- .../coercion/coerce-issue-49593-box-never.rs | 22 +++- 5 files changed, 246 insertions(+), 50 deletions(-) create mode 100644 tests/ui/coercion/coerce-issue-49593-box-never.fallback.stderr diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index d7b5c1ed5e15b..d0e02533f802b 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -694,31 +694,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { match selcx.select(&obligation.with(selcx.tcx(), trait_pred)) { // Uncertain or unimplemented. Ok(None) => { - if trait_pred.def_id() == unsize_did { - let self_ty = trait_pred.self_ty(); - let unsize_ty = trait_pred.trait_ref.args[1].expect_ty(); - debug!("coerce_unsized: ambiguous unsize case for {:?}", trait_pred); - match (self_ty.kind(), unsize_ty.kind()) { - (&ty::Infer(ty::TyVar(v)), ty::Dynamic(..)) - if self.type_var_is_sized(v) => - { - debug!("coerce_unsized: have sized infer {:?}", v); - coercion.obligations.push(obligation); - // `$0: Unsize` where we know that `$0: Sized`, try going - // for unsizing. - } - _ => { - // Some other case for `$0: Unsize`. Note that we - // hit this case even if `Something` is a sized type, so just - // don't do the coercion. - debug!("coerce_unsized: ambiguous unsize"); - return Err(TypeError::Mismatch); - } - } - } else { - debug!("coerce_unsized: early return - ambiguous"); - return Err(TypeError::Mismatch); - } + debug!("coerce_unsized: early return - ambiguous"); + return Err(TypeError::Mismatch); } Err(traits::Unimplemented) => { debug!("coerce_unsized: early return - can't prove obligation"); diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index c82f7a91168af..38320c85e1042 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -701,18 +701,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ret_ty.builtin_deref(true).unwrap() } - pub(crate) fn type_var_is_sized(&self, self_ty: ty::TyVid) -> bool { - let sized_did = self.tcx.lang_items().sized_trait(); - self.obligations_for_self_ty(self_ty).into_iter().any(|obligation| { - match obligation.predicate.kind().skip_binder() { - ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => { - Some(data.def_id()) == sized_did - } - _ => false, - } - }) - } - pub(crate) fn err_args(&self, len: usize, guar: ErrorGuaranteed) -> Vec> { let ty_error = Ty::new_error(self.tcx, guar); vec![ty_error; len] diff --git a/tests/ui/coercion/coerce-issue-49593-box-never.fallback.stderr b/tests/ui/coercion/coerce-issue-49593-box-never.fallback.stderr new file mode 100644 index 0000000000000..3401cd8635d8a --- /dev/null +++ b/tests/ui/coercion/coerce-issue-49593-box-never.fallback.stderr @@ -0,0 +1,117 @@ +error[E0277]: the size for values of type `dyn std::error::Error` cannot be known at compilation time + --> $DIR/coerce-issue-49593-box-never.rs:26:27 + | +LL | Box::<_ /* ! */>::new(x) + | --------------------- ^ doesn't have a size known at compile-time + | | + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `dyn std::error::Error` +note: required by a bound in `Box::::new` + --> $SRC_DIR/alloc/src/boxed.rs:LL:COL + +error[E0277]: the size for values of type `(dyn std::error::Error + 'static)` cannot be known at compilation time + --> $DIR/coerce-issue-49593-box-never.rs:32:19 + | +LL | raw_ptr_box::<_ /* ! */>(x) + | ^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `(dyn std::error::Error + 'static)` +note: required by an implicit `Sized` bound in `raw_ptr_box` + --> $DIR/coerce-issue-49593-box-never.rs:19:16 + | +LL | fn raw_ptr_box(t: T) -> *mut T { + | ^ required by the implicit `Sized` requirement on this type parameter in `raw_ptr_box` +help: consider relaxing the implicit `Sized` restriction + | +LL | fn raw_ptr_box(t: T) -> *mut T { + | ++++++++ + +error[E0277]: the size for values of type `(dyn std::error::Error + 'static)` cannot be known at compilation time + --> $DIR/coerce-issue-49593-box-never.rs:32:30 + | +LL | raw_ptr_box::<_ /* ! */>(x) + | ^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `(dyn std::error::Error + 'static)` + = note: all function arguments must have a statically known size + = help: unsized fn params are gated as an unstable feature + +error[E0277]: the size for values of type `dyn Xyz` cannot be known at compilation time + --> $DIR/coerce-issue-49593-box-never.rs:57:70 + | +LL | = /* Box<$0> is coerced to Box here */ Box::new(x.unwrap()); + | -------- ^^^^^^^^^^ doesn't have a size known at compile-time + | | + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `dyn Xyz` +note: required by a bound in `Box::::new` + --> $SRC_DIR/alloc/src/boxed.rs:LL:COL +help: consider removing this method call, as the receiver has type `Option<_>` and `Option<_>: Sized` trivially holds + | +LL - = /* Box<$0> is coerced to Box here */ Box::new(x.unwrap()); +LL + = /* Box<$0> is coerced to Box here */ Box::new(x); + | + +error[E0277]: the size for values of type `dyn Xyz` cannot be known at compilation time + --> $DIR/coerce-issue-49593-box-never.rs:57:72 + | +LL | = /* Box<$0> is coerced to Box here */ Box::new(x.unwrap()); + | ^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `dyn Xyz` +note: required by a bound in `Option::::unwrap` + --> $SRC_DIR/core/src/option.rs:LL:COL + +error[E0277]: the size for values of type `dyn Xyz` cannot be known at compilation time + --> $DIR/coerce-issue-49593-box-never.rs:50:35 + | +LL | let mut x /* : Option */ = None; + | ^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `dyn Xyz` +note: required by a bound in `None` + --> $SRC_DIR/core/src/option.rs:LL:COL + +error[E0308]: mismatched types + --> $DIR/coerce-issue-49593-box-never.rs:62:13 + | +LL | let mut x /* : Option */ = None; + | ---- expected due to this value +... +LL | x = Some(S); + | ^^^^^^^ expected `Option`, found `Option` + | + = note: expected enum `Option` + found enum `Option` + = help: `S` implements `Xyz` so you could box the found value and coerce it to the trait object `Box`, you will have to change the expected type as well + +error[E0277]: the size for values of type `dyn Xyz` cannot be known at compilation time + --> $DIR/coerce-issue-49593-box-never.rs:69:5 + | +LL | mem::swap(&mut x, &mut y); + | ^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `dyn Xyz` +note: required by an implicit `Sized` bound in `Option` + --> $SRC_DIR/core/src/option.rs:LL:COL + +error[E0308]: mismatched types + --> $DIR/coerce-issue-49593-box-never.rs:69:23 + | +LL | mem::swap(&mut x, &mut y); + | --------- ^^^^^^ expected `&mut Option`, found `&mut Option` + | | + | arguments to this function are incorrect + | + = note: expected mutable reference `&mut Option` + found mutable reference `&mut Option` + = help: `S` implements `Xyz` so you could box the found value and coerce it to the trait object `Box`, you will have to change the expected type as well +note: function defined here + --> $SRC_DIR/core/src/mem/mod.rs:LL:COL + +error: aborting due to 9 previous errors + +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/coercion/coerce-issue-49593-box-never.nofallback.stderr b/tests/ui/coercion/coerce-issue-49593-box-never.nofallback.stderr index 7222af43b0137..3401cd8635d8a 100644 --- a/tests/ui/coercion/coerce-issue-49593-box-never.nofallback.stderr +++ b/tests/ui/coercion/coerce-issue-49593-box-never.nofallback.stderr @@ -1,19 +1,117 @@ -error[E0277]: the trait bound `(): std::error::Error` is not satisfied - --> $DIR/coerce-issue-49593-box-never.rs:18:5 +error[E0277]: the size for values of type `dyn std::error::Error` cannot be known at compilation time + --> $DIR/coerce-issue-49593-box-never.rs:26:27 | LL | Box::<_ /* ! */>::new(x) - | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::error::Error` is not implemented for `()` + | --------------------- ^ doesn't have a size known at compile-time + | | + | required by a bound introduced by this call | - = note: required for the cast from `Box<()>` to `Box<(dyn std::error::Error + 'static)>` + = help: the trait `Sized` is not implemented for `dyn std::error::Error` +note: required by a bound in `Box::::new` + --> $SRC_DIR/alloc/src/boxed.rs:LL:COL -error[E0277]: the trait bound `(): std::error::Error` is not satisfied - --> $DIR/coerce-issue-49593-box-never.rs:24:5 +error[E0277]: the size for values of type `(dyn std::error::Error + 'static)` cannot be known at compilation time + --> $DIR/coerce-issue-49593-box-never.rs:32:19 | LL | raw_ptr_box::<_ /* ! */>(x) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::error::Error` is not implemented for `()` + | ^ doesn't have a size known at compile-time | - = note: required for the cast from `*mut ()` to `*mut (dyn std::error::Error + 'static)` + = help: the trait `Sized` is not implemented for `(dyn std::error::Error + 'static)` +note: required by an implicit `Sized` bound in `raw_ptr_box` + --> $DIR/coerce-issue-49593-box-never.rs:19:16 + | +LL | fn raw_ptr_box(t: T) -> *mut T { + | ^ required by the implicit `Sized` requirement on this type parameter in `raw_ptr_box` +help: consider relaxing the implicit `Sized` restriction + | +LL | fn raw_ptr_box(t: T) -> *mut T { + | ++++++++ + +error[E0277]: the size for values of type `(dyn std::error::Error + 'static)` cannot be known at compilation time + --> $DIR/coerce-issue-49593-box-never.rs:32:30 + | +LL | raw_ptr_box::<_ /* ! */>(x) + | ^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `(dyn std::error::Error + 'static)` + = note: all function arguments must have a statically known size + = help: unsized fn params are gated as an unstable feature + +error[E0277]: the size for values of type `dyn Xyz` cannot be known at compilation time + --> $DIR/coerce-issue-49593-box-never.rs:57:70 + | +LL | = /* Box<$0> is coerced to Box here */ Box::new(x.unwrap()); + | -------- ^^^^^^^^^^ doesn't have a size known at compile-time + | | + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `dyn Xyz` +note: required by a bound in `Box::::new` + --> $SRC_DIR/alloc/src/boxed.rs:LL:COL +help: consider removing this method call, as the receiver has type `Option<_>` and `Option<_>: Sized` trivially holds + | +LL - = /* Box<$0> is coerced to Box here */ Box::new(x.unwrap()); +LL + = /* Box<$0> is coerced to Box here */ Box::new(x); + | + +error[E0277]: the size for values of type `dyn Xyz` cannot be known at compilation time + --> $DIR/coerce-issue-49593-box-never.rs:57:72 + | +LL | = /* Box<$0> is coerced to Box here */ Box::new(x.unwrap()); + | ^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `dyn Xyz` +note: required by a bound in `Option::::unwrap` + --> $SRC_DIR/core/src/option.rs:LL:COL + +error[E0277]: the size for values of type `dyn Xyz` cannot be known at compilation time + --> $DIR/coerce-issue-49593-box-never.rs:50:35 + | +LL | let mut x /* : Option */ = None; + | ^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `dyn Xyz` +note: required by a bound in `None` + --> $SRC_DIR/core/src/option.rs:LL:COL + +error[E0308]: mismatched types + --> $DIR/coerce-issue-49593-box-never.rs:62:13 + | +LL | let mut x /* : Option */ = None; + | ---- expected due to this value +... +LL | x = Some(S); + | ^^^^^^^ expected `Option`, found `Option` + | + = note: expected enum `Option` + found enum `Option` + = help: `S` implements `Xyz` so you could box the found value and coerce it to the trait object `Box`, you will have to change the expected type as well + +error[E0277]: the size for values of type `dyn Xyz` cannot be known at compilation time + --> $DIR/coerce-issue-49593-box-never.rs:69:5 + | +LL | mem::swap(&mut x, &mut y); + | ^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `dyn Xyz` +note: required by an implicit `Sized` bound in `Option` + --> $SRC_DIR/core/src/option.rs:LL:COL + +error[E0308]: mismatched types + --> $DIR/coerce-issue-49593-box-never.rs:69:23 + | +LL | mem::swap(&mut x, &mut y); + | --------- ^^^^^^ expected `&mut Option`, found `&mut Option` + | | + | arguments to this function are incorrect + | + = note: expected mutable reference `&mut Option` + found mutable reference `&mut Option` + = help: `S` implements `Xyz` so you could box the found value and coerce it to the trait object `Box`, you will have to change the expected type as well +note: function defined here + --> $SRC_DIR/core/src/mem/mod.rs:LL:COL -error: aborting due to 2 previous errors +error: aborting due to 9 previous errors -For more information about this error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/coercion/coerce-issue-49593-box-never.rs b/tests/ui/coercion/coerce-issue-49593-box-never.rs index e556959204590..6de5ef76f274d 100644 --- a/tests/ui/coercion/coerce-issue-49593-box-never.rs +++ b/tests/ui/coercion/coerce-issue-49593-box-never.rs @@ -1,5 +1,13 @@ +//! This test was supposed to test that unsizing an uninferred but +//! `Sized` type works and will let inference happen later. +//! The issue was that what instead happened was that the inference +//! variable got equated to the unsized type, and subsequently failed +//! the `Sized` check. +//! +//! This was a wart in our coercion code, so it was removed to be instead +//! implemented in the trait system. + //@ revisions: nofallback fallback -//@[fallback] check-pass #![feature(never_type)] #![cfg_attr(fallback, feature(never_type_fallback))] @@ -16,13 +24,14 @@ fn foo(x: !) -> Box { // Method resolution will generate new inference vars and relate them. // Thus fallback will not fall back to `!`, but `()` instead. Box::<_ /* ! */>::new(x) - //[nofallback]~^ ERROR trait bound `(): std::error::Error` is not satisfied + //~^ ERROR cannot be known at compilation time } fn foo_raw_ptr(x: !) -> *mut dyn Error { /* *mut $0 is coerced to *mut Error here */ raw_ptr_box::<_ /* ! */>(x) - //[nofallback]~^ ERROR trait bound `(): std::error::Error` is not satisfied + //~^ ERROR cannot be known at compilation time + //~| ERROR cannot be known at compilation time } fn no_coercion(d: *mut dyn Error) -> *mut dyn Error { @@ -39,20 +48,27 @@ impl Xyz for T {} fn foo_no_never() { let mut x /* : Option */ = None; + //~^ ERROR cannot be known at compilation time + let mut first_iter = false; loop { if !first_iter { let y: Box = /* Box<$0> is coerced to Box here */ Box::new(x.unwrap()); + //~^ ERROR cannot be known at compilation time + //~| ERROR cannot be known at compilation time } x = Some(S); + //~^ ERROR mismatched types first_iter = true; } let mut y: Option = None; // assert types are equal mem::swap(&mut x, &mut y); + //~^ ERROR cannot be known at compilation time + //~| ERROR mismatched types } fn main() {}