only suppress coercion error if type is definitely unsized
This commit is contained in:
parent
789dd0b2a2
commit
9f70efb31a
@ -1595,7 +1595,7 @@ pub(crate) fn coerce_inner<'a>(
|
||||
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 {
|
||||
@ -1614,8 +1614,7 @@ pub(crate) fn coerce_inner<'a>(
|
||||
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);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
@ -1896,15 +1895,24 @@ fn add_impl_trait_explanation<'a>(
|
||||
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> {
|
||||
|
11
tests/ui/typeck/return-dyn-type-mismatch-2.rs
Normal file
11
tests/ui/typeck/return-dyn-type-mismatch-2.rs
Normal file
@ -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
tests/ui/typeck/return-dyn-type-mismatch-2.stderr
Normal file
15
tests/ui/typeck/return-dyn-type-mismatch-2.stderr
Normal file
@ -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
tests/ui/typeck/return-dyn-type-mismatch.rs
Normal file
21
tests/ui/typeck/return-dyn-type-mismatch.rs
Normal file
@ -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
tests/ui/typeck/return-dyn-type-mismatch.stderr
Normal file
15
tests/ui/typeck/return-dyn-type-mismatch.stderr
Normal file
@ -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`.
|
Loading…
Reference in New Issue
Block a user