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,
|
span: Span,
|
||||||
) -> bool;
|
) -> 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>(
|
fn partially_normalize_associated_types_in<T>(
|
||||||
&self,
|
&self,
|
||||||
cause: ObligationCause<'tcx>,
|
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)
|
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
|
/// Normalizes associated types in `value`, potentially returning
|
||||||
/// new obligations that must further be processed.
|
/// new obligations that must further be processed.
|
||||||
fn partially_normalize_associated_types_in<T>(
|
fn partially_normalize_associated_types_in<T>(
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use super::method::MethodCallee;
|
use super::method::MethodCallee;
|
||||||
use super::{Expectation, FnCtxt, TupleArgumentsFlag};
|
use super::{DefIdOrName, Expectation, FnCtxt, TupleArgumentsFlag};
|
||||||
use crate::type_error_struct;
|
use crate::type_error_struct;
|
||||||
|
|
||||||
use rustc_errors::{struct_span_err, Applicability, Diagnostic};
|
use rustc_errors::{struct_span_err, Applicability, Diagnostic};
|
||||||
@ -24,7 +24,8 @@
|
|||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
use rustc_target::spec::abi;
|
use rustc_target::spec::abi;
|
||||||
use rustc_trait_selection::autoderef::Autoderef;
|
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;
|
use std::iter;
|
||||||
|
|
||||||
@ -471,7 +472,25 @@ fn confirm_builtin_call(
|
|||||||
};
|
};
|
||||||
|
|
||||||
if !self.maybe_suggest_bad_array_definition(&mut err, call_expr, callee_expr) {
|
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) {
|
if let Some(span) = self.tcx.hir().res_span(def) {
|
||||||
|
@ -35,7 +35,6 @@
|
|||||||
use hir::def_id::LOCAL_CRATE;
|
use hir::def_id::LOCAL_CRATE;
|
||||||
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed};
|
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::lang_items::LangItem;
|
|
||||||
use rustc_middle::mir::Mutability;
|
use rustc_middle::mir::Mutability;
|
||||||
use rustc_middle::ty::adjustment::AllowTwoPhase;
|
use rustc_middle::ty::adjustment::AllowTwoPhase;
|
||||||
use rustc_middle::ty::cast::{CastKind, CastTy};
|
use rustc_middle::ty::cast::{CastKind, CastTy};
|
||||||
@ -47,7 +46,6 @@
|
|||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
use rustc_trait_selection::infer::InferCtxtExt;
|
use rustc_trait_selection::infer::InferCtxtExt;
|
||||||
use rustc_trait_selection::traits;
|
|
||||||
use rustc_trait_selection::traits::error_reporting::report_object_safety_error;
|
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
|
/// Reifies a cast check to be checked once we have full type information for
|
||||||
@ -97,7 +95,7 @@ fn pointer_kind(
|
|||||||
return Err(reported);
|
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));
|
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);
|
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.cast_ty.has_infer_types()
|
||||||
{
|
{
|
||||||
self.report_cast_to_unsized_type(fcx);
|
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
|
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,
|
&self,
|
||||||
expr: &Expr<'_>,
|
expr: &Expr<'_>,
|
||||||
found: Ty<'tcx>,
|
found: Ty<'tcx>,
|
||||||
@ -1130,7 +1133,7 @@ pub(crate) fn consider_removing_semicolon(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum DefIdOrName {
|
pub enum DefIdOrName {
|
||||||
DefId(DefId),
|
DefId(DefId),
|
||||||
Name(&'static str),
|
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)`
|
| -------------------------------------------------- `get_function` defined here returns `&dyn Fn() -> (dyn Trait + 'static)`
|
||||||
...
|
...
|
||||||
LL | let t: &dyn Trait = &get_function()();
|
LL | let t: &dyn Trait = &get_function()();
|
||||||
| ^^^^^^^^^^^^^^--
|
| ^^^^^^^^^^^^^^ this trait object returns an unsized value `(dyn Trait + 'static)`, so it cannot be called
|
||||||
| |
|
|
||||||
| call expression requires function
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user