From 9f19b50b6b8bfcf7690fa8f0bf648081a096f7ae Mon Sep 17 00:00:00 2001 From: yifei Date: Thu, 26 May 2022 12:27:06 +0800 Subject: [PATCH] better tip for return `impl ?Sized` --- compiler/rustc_typeck/src/check/check.rs | 20 +++++++++++++++++++ src/test/ui/return/return-impl-maybe-sized.rs | 5 +++++ .../ui/return/return-impl-maybe-sized.stderr | 8 ++++++++ 3 files changed, 33 insertions(+) create mode 100644 src/test/ui/return/return-impl-maybe-sized.rs create mode 100644 src/test/ui/return/return-impl-maybe-sized.stderr diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 3e76738cc5d9..0a8f387054ad 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -3,6 +3,7 @@ use super::compare_method::check_type_bounds; use super::compare_method::{compare_const_impl, compare_impl_method, compare_ty_impl}; use super::*; +use hir::{GenericBound, PolyTraitRef, TraitBoundModifier}; use rustc_attr as attr; use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan}; use rustc_hir as hir; @@ -96,6 +97,25 @@ pub(super) fn check_fn<'a, 'tcx>( let declared_ret_ty = fn_sig.output(); + if let ty::Opaque(def_id, _) = *declared_ret_ty.kind() { + let bounds = match &tcx.hir().expect_item(def_id.expect_local()).kind { + ItemKind::OpaqueTy(ty) => ty.bounds, + _ => bug!("unexpected opaque type"), + }; + + let sized_def_id = tcx.require_lang_item(LangItem::Sized, None); + if bounds.iter().any(|bound| match bound { + GenericBound::Trait(PolyTraitRef { trait_ref, .. }, TraitBoundModifier::Maybe) + if trait_ref.path.res.def_id() == sized_def_id => + { + true + } + _ => false, + }) { + sess.span_err(decl.output.span(), "return type should be sized"); + } + } + let ret_ty = fcx.register_infer_ok_obligations(fcx.infcx.replace_opaque_types_with_inference_vars( declared_ret_ty, diff --git a/src/test/ui/return/return-impl-maybe-sized.rs b/src/test/ui/return/return-impl-maybe-sized.rs new file mode 100644 index 000000000000..d8fa1fa6b833 --- /dev/null +++ b/src/test/ui/return/return-impl-maybe-sized.rs @@ -0,0 +1,5 @@ +// Regression test for issue #97226 + +fn test_fn() -> impl ?Sized {} //~ ERROR return type should be sized + +fn main() {} diff --git a/src/test/ui/return/return-impl-maybe-sized.stderr b/src/test/ui/return/return-impl-maybe-sized.stderr new file mode 100644 index 000000000000..3044379b4373 --- /dev/null +++ b/src/test/ui/return/return-impl-maybe-sized.stderr @@ -0,0 +1,8 @@ +error: return type should be sized + --> $DIR/return-impl-maybe-sized.rs:3:17 + | +LL | fn test_fn() -> impl ?Sized {} + | ^^^^^^^^^^^ + +error: aborting due to previous error +