From dc0db358abe19481e475e10c32149b53370f1a1c Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 30 May 2024 05:57:31 +0200 Subject: Merging upstream version 1.72.1+dfsg1. Signed-off-by: Daniel Baumann --- compiler/rustc_hir_typeck/src/callee.rs | 133 +++++++++++++++++++++----------- 1 file changed, 88 insertions(+), 45 deletions(-) (limited to 'compiler/rustc_hir_typeck/src/callee.rs') diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index 655ab94eb..f306653c1 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -6,8 +6,9 @@ use crate::type_error_struct; use rustc_ast::util::parser::PREC_POSTFIX; use rustc_errors::{struct_span_err, Applicability, Diagnostic, ErrorGuaranteed, StashKey}; use rustc_hir as hir; -use rustc_hir::def::{self, CtorKind, Namespace, Res}; +use rustc_hir::def::{self, CtorKind, DefKind, Namespace, Res}; use rustc_hir::def_id::DefId; +use rustc_hir::HirId; use rustc_hir_analysis::autoderef::Autoderef; use rustc_infer::{ infer, @@ -89,7 +90,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ => self.check_expr(callee_expr), }; - let expr_ty = self.structurally_resolved_type(call_expr.span, original_callee_ty); + let expr_ty = self.structurally_resolve_type(call_expr.span, original_callee_ty); let mut autoderef = self.autoderef(callee_expr.span, expr_ty); let mut result = None; @@ -138,7 +139,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { autoderef: &Autoderef<'a, 'tcx>, ) -> Option> { let adjusted_ty = - self.structurally_resolved_type(autoderef.span(), autoderef.final_ty(false)); + self.structurally_resolve_type(autoderef.span(), autoderef.final_ty(false)); // If the callee is a bare function or a closure, then we're all set. match *adjusted_ty.kind() { @@ -232,12 +233,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let Some(trait_def_id) = opt_trait_def_id else { continue }; let opt_input_type = opt_arg_exprs.map(|arg_exprs| { - self.tcx.mk_tup_from_iter(arg_exprs.iter().map(|e| { - self.next_ty_var(TypeVariableOrigin { - kind: TypeVariableOriginKind::TypeInference, - span: e.span, - }) - })) + Ty::new_tup_from_iter( + self.tcx, + arg_exprs.iter().map(|e| { + self.next_ty_var(TypeVariableOrigin { + kind: TypeVariableOriginKind::TypeInference, + span: e.span, + }) + }), + ) }); if let Some(ok) = self.lookup_method_in_trait( @@ -376,15 +380,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected: Expectation<'tcx>, ) -> Ty<'tcx> { let (fn_sig, def_id) = match *callee_ty.kind() { - ty::FnDef(def_id, subst) => { - let fn_sig = self.tcx.fn_sig(def_id).subst(self.tcx, subst); + ty::FnDef(def_id, substs) => { + self.enforce_context_effects(call_expr.hir_id, call_expr.span, def_id, substs); + let fn_sig = self.tcx.fn_sig(def_id).subst(self.tcx, substs); // Unit testing: function items annotated with // `#[rustc_evaluate_where_clauses]` trigger special output // to let us test the trait evaluation system. if self.tcx.has_attr(def_id, sym::rustc_evaluate_where_clauses) { let predicates = self.tcx.predicates_of(def_id); - let predicates = predicates.instantiate(self.tcx, subst); + let predicates = predicates.instantiate(self.tcx, substs); for (predicate, predicate_span) in predicates { let obligation = Obligation::new( self.tcx, @@ -405,6 +410,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } (fn_sig, Some(def_id)) } + // FIXME(effects): these arms should error because we can't enforce them ty::FnPtr(sig) => (sig, None), _ => { for arg in arg_exprs { @@ -420,25 +426,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .steal_diagnostic(segment.ident.span, StashKey::CallIntoMethod) { // Try suggesting `foo(a)` -> `a.foo()` if possible. - if let Some(ty) = - self.suggest_call_as_method( - &mut diag, - segment, - arg_exprs, - call_expr, - expected - ) - { - diag.emit(); - return ty; - } else { - diag.emit(); - } + self.suggest_call_as_method( + &mut diag, + segment, + arg_exprs, + call_expr, + expected + ); + diag.emit(); } let err = self.report_invalid_callee(call_expr, callee_expr, callee_ty, arg_exprs); - return self.tcx.ty_error(err); + return Ty::new_error(self.tcx, err); } }; @@ -476,6 +476,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx.require_lang_item(hir::LangItem::Tuple, Some(sp)), traits::ObligationCause::new(sp, self.body_id, traits::RustCall), ); + self.require_type_is_sized(ty, sp, traits::RustCall); } else { self.tcx.sess.span_err( sp, @@ -496,9 +497,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { arg_exprs: &'tcx [hir::Expr<'tcx>], call_expr: &'tcx hir::Expr<'tcx>, expected: Expectation<'tcx>, - ) -> Option> { + ) { if let [callee_expr, rest @ ..] = arg_exprs { - let callee_ty = self.typeck_results.borrow().expr_ty_adjusted_opt(callee_expr)?; + let Some(callee_ty) = self.typeck_results.borrow().expr_ty_adjusted_opt(callee_expr) else { + return; + }; // First, do a probe with `IsSuggestion(true)` to avoid emitting // any strange errors. If it's successful, then we'll do a true @@ -513,7 +516,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ProbeScope::AllTraits, expected.only_has_type(self), ) else { - return None; + return; }; let pick = self.confirm_method( @@ -525,7 +528,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { segment, ); if pick.illegal_sized_bound.is_some() { - return None; + return; } let up_to_rcvr_span = segment.ident.span.until(callee_expr.span); @@ -567,22 +570,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { sugg, Applicability::MaybeIncorrect, ); - - // Let's check the method fully now - let return_ty = self.check_method_argument_types( - segment.ident.span, - call_expr, - Ok(pick.callee), - rest, - TupleArgumentsFlag::DontTupleArguments, - expected, - ); - - return Some(return_ty); } } - - None } fn report_invalid_callee( @@ -756,6 +745,60 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn_sig.output() } + #[tracing::instrument(level = "debug", skip(self, span))] + pub(super) fn enforce_context_effects( + &self, + call_expr_hir: HirId, + span: Span, + callee_did: DefId, + callee_substs: SubstsRef<'tcx>, + ) { + let tcx = self.tcx; + + if !tcx.features().effects || tcx.sess.opts.unstable_opts.unleash_the_miri_inside_of_you { + return; + } + + // Compute the constness required by the context. + let context = tcx.hir().enclosing_body_owner(call_expr_hir); + let const_context = tcx.hir().body_const_context(context); + + let kind = tcx.def_kind(context.to_def_id()); + debug_assert_ne!(kind, DefKind::ConstParam); + + if tcx.has_attr(context.to_def_id(), sym::rustc_do_not_const_check) { + trace!("do not const check this context"); + return; + } + + let effect = match const_context { + Some(hir::ConstContext::Static(_) | hir::ConstContext::Const) => tcx.consts.false_, + Some(hir::ConstContext::ConstFn) => { + let substs = ty::InternalSubsts::identity_for_item(tcx, context); + substs.host_effect_param().expect("ConstContext::Maybe must have host effect param") + } + None => tcx.consts.true_, + }; + + let generics = tcx.generics_of(callee_did); + + trace!(?effect, ?generics, ?callee_substs); + + if let Some(idx) = generics.host_effect_index { + let param = callee_substs.const_at(idx); + let cause = self.misc(span); + match self.at(&cause, self.param_env).eq(infer::DefineOpaqueTypes::No, effect, param) { + Ok(infer::InferOk { obligations, value: () }) => { + self.register_predicates(obligations); + } + Err(e) => { + // FIXME(effects): better diagnostic + self.err_ctxt().report_mismatched_consts(&cause, effect, param, e).emit(); + } + } + } + } + fn confirm_overloaded_call( &self, call_expr: &'tcx hir::Expr<'tcx>, -- cgit v1.2.3