Point out when a callable is not actually callable because its return is not sized
This commit is contained in:
parent
b44197abb0
commit
1254b32479
@ -24,6 +24,13 @@ fn type_is_copy_modulo_regions(
|
||||
span: Span,
|
||||
) -> bool;
|
||||
|
||||
fn type_is_sized_modulo_regions(
|
||||
&self,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
span: Span,
|
||||
) -> bool;
|
||||
|
||||
fn partially_normalize_associated_types_in<T>(
|
||||
&self,
|
||||
cause: ObligationCause<'tcx>,
|
||||
@ -74,6 +81,16 @@ fn type_is_copy_modulo_regions(
|
||||
traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, copy_def_id, span)
|
||||
}
|
||||
|
||||
fn type_is_sized_modulo_regions(
|
||||
&self,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
span: Span,
|
||||
) -> bool {
|
||||
let lang_item = self.tcx.require_lang_item(LangItem::Sized, None);
|
||||
traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, lang_item, span)
|
||||
}
|
||||
|
||||
/// Normalizes associated types in `value`, potentially returning
|
||||
/// new obligations that must further be processed.
|
||||
fn partially_normalize_associated_types_in<T>(
|
||||
|
@ -1,5 +1,5 @@
|
||||
use super::method::MethodCallee;
|
||||
use super::{Expectation, FnCtxt, TupleArgumentsFlag};
|
||||
use super::{DefIdOrName, Expectation, FnCtxt, TupleArgumentsFlag};
|
||||
use crate::type_error_struct;
|
||||
|
||||
use rustc_errors::{struct_span_err, Applicability, Diagnostic};
|
||||
@ -24,7 +24,8 @@
|
||||
use rustc_span::Span;
|
||||
use rustc_target::spec::abi;
|
||||
use rustc_trait_selection::autoderef::Autoderef;
|
||||
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
|
||||
use rustc_trait_selection::infer::InferCtxtExt as _;
|
||||
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
|
||||
|
||||
use std::iter;
|
||||
|
||||
@ -471,7 +472,25 @@ fn confirm_builtin_call(
|
||||
};
|
||||
|
||||
if !self.maybe_suggest_bad_array_definition(&mut err, call_expr, callee_expr) {
|
||||
err.span_label(call_expr.span, "call expression requires function");
|
||||
if let Some((maybe_def, output_ty, _)) = self.extract_callable_info(callee_expr, callee_ty)
|
||||
&& !self.type_is_sized_modulo_regions(self.param_env, output_ty, callee_expr.span)
|
||||
{
|
||||
let descr = match maybe_def {
|
||||
DefIdOrName::DefId(def_id) => self.tcx.def_kind(def_id).descr(def_id),
|
||||
DefIdOrName::Name(name) => name,
|
||||
};
|
||||
err.span_label(
|
||||
callee_expr.span,
|
||||
format!("this {descr} returns an unsized value `{output_ty}`, so it cannot be called")
|
||||
);
|
||||
if let DefIdOrName::DefId(def_id) = maybe_def
|
||||
&& let Some(def_span) = self.tcx.hir().span_if_local(def_id)
|
||||
{
|
||||
err.span_label(def_span, "the callable type is defined here");
|
||||
}
|
||||
} else {
|
||||
err.span_label(call_expr.span, "call expression requires function");
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(span) = self.tcx.hir().res_span(def) {
|
||||
|
@ -35,7 +35,6 @@
|
||||
use hir::def_id::LOCAL_CRATE;
|
||||
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_middle::mir::Mutability;
|
||||
use rustc_middle::ty::adjustment::AllowTwoPhase;
|
||||
use rustc_middle::ty::cast::{CastKind, CastTy};
|
||||
@ -47,7 +46,6 @@
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::Span;
|
||||
use rustc_trait_selection::infer::InferCtxtExt;
|
||||
use rustc_trait_selection::traits;
|
||||
use rustc_trait_selection::traits::error_reporting::report_object_safety_error;
|
||||
|
||||
/// Reifies a cast check to be checked once we have full type information for
|
||||
@ -97,7 +95,7 @@ fn pointer_kind(
|
||||
return Err(reported);
|
||||
}
|
||||
|
||||
if self.type_is_known_to_be_sized_modulo_regions(t, span) {
|
||||
if self.type_is_sized_modulo_regions(self.param_env, t, span) {
|
||||
return Ok(Some(PointerKind::Thin));
|
||||
}
|
||||
|
||||
@ -705,7 +703,7 @@ pub fn check(mut self, fcx: &FnCtxt<'a, 'tcx>) {
|
||||
|
||||
debug!("check_cast({}, {:?} as {:?})", self.expr.hir_id, self.expr_ty, self.cast_ty);
|
||||
|
||||
if !fcx.type_is_known_to_be_sized_modulo_regions(self.cast_ty, self.span)
|
||||
if !fcx.type_is_sized_modulo_regions(fcx.param_env, self.cast_ty, self.span)
|
||||
&& !self.cast_ty.has_infer_types()
|
||||
{
|
||||
self.report_cast_to_unsized_type(fcx);
|
||||
@ -1084,10 +1082,3 @@ fn fuzzy_provenance_int2ptr_lint(&self, fcx: &FnCtxt<'a, 'tcx>) {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
fn type_is_known_to_be_sized_modulo_regions(&self, ty: Ty<'tcx>, span: Span) -> bool {
|
||||
let lang_item = self.tcx.require_lang_item(LangItem::Sized, None);
|
||||
traits::type_known_to_meet_bound_modulo_regions(self, self.param_env, ty, lang_item, span)
|
||||
}
|
||||
}
|
||||
|
@ -144,7 +144,10 @@ pub(crate) fn suggest_fn_call(
|
||||
false
|
||||
}
|
||||
|
||||
fn extract_callable_info(
|
||||
/// Extracts information about a callable type for diagnostics. This is a
|
||||
/// heuristic -- it doesn't necessarily mean that a type is always callable,
|
||||
/// because the callable type must also be well-formed to be called.
|
||||
pub(in super::super) fn extract_callable_info(
|
||||
&self,
|
||||
expr: &Expr<'_>,
|
||||
found: Ty<'tcx>,
|
||||
@ -1130,7 +1133,7 @@ pub(crate) fn consider_removing_semicolon(
|
||||
}
|
||||
}
|
||||
|
||||
enum DefIdOrName {
|
||||
pub enum DefIdOrName {
|
||||
DefId(DefId),
|
||||
Name(&'static str),
|
||||
}
|
||||
|
@ -5,9 +5,7 @@ LL | fn get_function<'a>() -> &'a dyn Fn() -> dyn Trait {
|
||||
| -------------------------------------------------- `get_function` defined here returns `&dyn Fn() -> (dyn Trait + 'static)`
|
||||
...
|
||||
LL | let t: &dyn Trait = &get_function()();
|
||||
| ^^^^^^^^^^^^^^--
|
||||
| |
|
||||
| call expression requires function
|
||||
| ^^^^^^^^^^^^^^ this trait object returns an unsized value `(dyn Trait + 'static)`, so it cannot be called
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user