Skip to content

Commit

Permalink
Rollup merge of rust-lang#112215 - compiler-errors:check-sized-better…
Browse files Browse the repository at this point in the history
…, r=cjgillot

only suppress coercion error if type is definitely unsized

we previously suppressed coercion errors when the return type was `dyn Trait` because we expect a far more descriptive `Sized` trait error to be emitted instead, however the code that does this suppression does not consider where-clause predicates since it just looked at the HIR. let's do that instead by creating an obligation and checking if it may hold.

fixes rust-lang#110683
fixes rust-lang#112208
  • Loading branch information
matthiaskrgr authored Jun 3, 2023
2 parents 6eccb04 + 9f70efb commit a6e3036
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 11 deletions.
30 changes: 19 additions & 11 deletions compiler/rustc_hir_typeck/src/coercion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1595,7 +1595,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
Some(blk_id),
);
if !fcx.tcx.features().unsized_locals {
unsized_return = self.is_return_ty_unsized(fcx, blk_id);
unsized_return = self.is_return_ty_definitely_unsized(fcx);
}
if let Some(expression) = expression
&& let hir::ExprKind::Loop(loop_blk, ..) = expression.kind {
Expand All @@ -1614,8 +1614,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
None,
);
if !fcx.tcx.features().unsized_locals {
let id = fcx.tcx.hir().parent_id(id);
unsized_return = self.is_return_ty_unsized(fcx, id);
unsized_return = self.is_return_ty_definitely_unsized(fcx);
}
}
_ => {
Expand Down Expand Up @@ -1896,15 +1895,24 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
err.help("you could instead create a new `enum` with a variant for each returned type");
}

fn is_return_ty_unsized<'a>(&self, fcx: &FnCtxt<'a, 'tcx>, blk_id: hir::HirId) -> bool {
if let Some((_, fn_decl, _)) = fcx.get_fn_decl(blk_id)
&& let hir::FnRetTy::Return(ty) = fn_decl.output
&& let ty = fcx.astconv().ast_ty_to_ty( ty)
&& let ty::Dynamic(..) = ty.kind()
{
return true;
/// Checks whether the return type is unsized via an obligation, which makes
/// sure we consider `dyn Trait: Sized` where clauses, which are trivially
/// false but technically valid for typeck.
fn is_return_ty_definitely_unsized(&self, fcx: &FnCtxt<'_, 'tcx>) -> bool {
if let Some(sig) = fcx.body_fn_sig() {
!fcx.predicate_may_hold(&Obligation::new(
fcx.tcx,
ObligationCause::dummy(),
fcx.param_env,
ty::TraitRef::new(
fcx.tcx,
fcx.tcx.require_lang_item(hir::LangItem::Sized, None),
[sig.output()],
),
))
} else {
false
}
false
}

pub fn complete<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Ty<'tcx> {
Expand Down
11 changes: 11 additions & 0 deletions tests/ui/typeck/return-dyn-type-mismatch-2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
trait Trait<T> {}

fn foo<T>() -> dyn Trait<T>
where
dyn Trait<T>: Sized, // pesky sized predicate
{
42
//~^ ERROR mismatched types
}

fn main() {}
15 changes: 15 additions & 0 deletions tests/ui/typeck/return-dyn-type-mismatch-2.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
error[E0308]: mismatched types
--> $DIR/return-dyn-type-mismatch-2.rs:7:5
|
LL | fn foo<T>() -> dyn Trait<T>
| ------------ expected `(dyn Trait<T> + 'static)` because of return type
...
LL | 42
| ^^ expected `dyn Trait`, found integer
|
= note: expected trait object `(dyn Trait<T> + 'static)`
found type `{integer}`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0308`.
21 changes: 21 additions & 0 deletions tests/ui/typeck/return-dyn-type-mismatch.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
pub trait TestTrait {
type MyType;

fn func() -> Option<Self>
where
Self: Sized;
}

impl<T> dyn TestTrait<MyType = T>
where
Self: Sized, // pesky sized predicate
{
fn other_func() -> dyn TestTrait<MyType = T> {
match Self::func() {
None => None,
//~^ ERROR mismatched types
}
}
}

fn main() {}
15 changes: 15 additions & 0 deletions tests/ui/typeck/return-dyn-type-mismatch.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
error[E0308]: mismatched types
--> $DIR/return-dyn-type-mismatch.rs:15:21
|
LL | fn other_func() -> dyn TestTrait<MyType = T> {
| ------------------------- expected `(dyn TestTrait<MyType = T> + 'static)` because of return type
LL | match Self::func() {
LL | None => None,
| ^^^^ expected `dyn TestTrait`, found `Option<_>`
|
= note: expected trait object `(dyn TestTrait<MyType = T> + 'static)`
found enum `Option<_>`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0308`.

0 comments on commit a6e3036

Please sign in to comment.