Skip to content

Commit a6e3036

Browse files
authored
Rollup merge of rust-lang#112215 - compiler-errors:check-sized-better, 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
2 parents 6eccb04 + 9f70efb commit a6e3036

5 files changed

+81
-11
lines changed

compiler/rustc_hir_typeck/src/coercion.rs

+19-11
Original file line numberDiff line numberDiff line change
@@ -1595,7 +1595,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
15951595
Some(blk_id),
15961596
);
15971597
if !fcx.tcx.features().unsized_locals {
1598-
unsized_return = self.is_return_ty_unsized(fcx, blk_id);
1598+
unsized_return = self.is_return_ty_definitely_unsized(fcx);
15991599
}
16001600
if let Some(expression) = expression
16011601
&& let hir::ExprKind::Loop(loop_blk, ..) = expression.kind {
@@ -1614,8 +1614,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
16141614
None,
16151615
);
16161616
if !fcx.tcx.features().unsized_locals {
1617-
let id = fcx.tcx.hir().parent_id(id);
1618-
unsized_return = self.is_return_ty_unsized(fcx, id);
1617+
unsized_return = self.is_return_ty_definitely_unsized(fcx);
16191618
}
16201619
}
16211620
_ => {
@@ -1896,15 +1895,24 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
18961895
err.help("you could instead create a new `enum` with a variant for each returned type");
18971896
}
18981897

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

19101918
pub fn complete<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Ty<'tcx> {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
trait Trait<T> {}
2+
3+
fn foo<T>() -> dyn Trait<T>
4+
where
5+
dyn Trait<T>: Sized, // pesky sized predicate
6+
{
7+
42
8+
//~^ ERROR mismatched types
9+
}
10+
11+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/return-dyn-type-mismatch-2.rs:7:5
3+
|
4+
LL | fn foo<T>() -> dyn Trait<T>
5+
| ------------ expected `(dyn Trait<T> + 'static)` because of return type
6+
...
7+
LL | 42
8+
| ^^ expected `dyn Trait`, found integer
9+
|
10+
= note: expected trait object `(dyn Trait<T> + 'static)`
11+
found type `{integer}`
12+
13+
error: aborting due to previous error
14+
15+
For more information about this error, try `rustc --explain E0308`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
pub trait TestTrait {
2+
type MyType;
3+
4+
fn func() -> Option<Self>
5+
where
6+
Self: Sized;
7+
}
8+
9+
impl<T> dyn TestTrait<MyType = T>
10+
where
11+
Self: Sized, // pesky sized predicate
12+
{
13+
fn other_func() -> dyn TestTrait<MyType = T> {
14+
match Self::func() {
15+
None => None,
16+
//~^ ERROR mismatched types
17+
}
18+
}
19+
}
20+
21+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/return-dyn-type-mismatch.rs:15:21
3+
|
4+
LL | fn other_func() -> dyn TestTrait<MyType = T> {
5+
| ------------------------- expected `(dyn TestTrait<MyType = T> + 'static)` because of return type
6+
LL | match Self::func() {
7+
LL | None => None,
8+
| ^^^^ expected `dyn TestTrait`, found `Option<_>`
9+
|
10+
= note: expected trait object `(dyn TestTrait<MyType = T> + 'static)`
11+
found enum `Option<_>`
12+
13+
error: aborting due to previous error
14+
15+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)