From 23412dd10574dc30c2f8e6a1df705dab06434358 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Mon, 6 Feb 2023 09:06:01 +0000 Subject: [PATCH 1/8] Remove `arena_cache` modifier from `upstream_monomorphizations_for` --- compiler/rustc_middle/src/query/mod.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 4cebe416354a9..7aa9282b9bece 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1541,7 +1541,6 @@ rustc_queries! { query upstream_monomorphizations_for(def_id: DefId) -> Option<&'tcx FxHashMap, CrateNum>> { - arena_cache desc { |tcx| "collecting available upstream monomorphizations for `{}`", tcx.def_path_str(def_id), From 0ddf249532f188cdd947a333dfd8a009cc517ccc Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 6 Feb 2023 21:11:03 +0000 Subject: [PATCH 2/8] Avoid locking the global context across the `after_expansion` callback --- compiler/rustc_driver_impl/src/lib.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 02e0b042ad263..1da13afecfa93 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -326,14 +326,16 @@ fn run_compiler( } } - let mut gctxt = queries.global_ctxt()?; + // Make sure name resolution and macro expansion is run. + queries.global_ctxt()?; + if callbacks.after_expansion(compiler, queries) == Compilation::Stop { return early_exit(); } // Make sure the `output_filenames` query is run for its side // effects of writing the dep-info and reporting errors. - gctxt.enter(|tcx| tcx.output_filenames(())); + queries.global_ctxt()?.enter(|tcx| tcx.output_filenames(())); if sess.opts.output_types.contains_key(&OutputType::DepInfo) && sess.opts.output_types.len() == 1 @@ -345,7 +347,7 @@ fn run_compiler( return early_exit(); } - gctxt.enter(|tcx| { + queries.global_ctxt()?.enter(|tcx| { let result = tcx.analysis(()); if sess.opts.unstable_opts.save_analysis { let crate_name = tcx.crate_name(LOCAL_CRATE); @@ -362,8 +364,6 @@ fn run_compiler( result })?; - drop(gctxt); - if callbacks.after_analysis(compiler, queries) == Compilation::Stop { return early_exit(); } From 4c053668d6b170232fadb37082f7c590ce84aa4f Mon Sep 17 00:00:00 2001 From: Nathan Fenner Date: Mon, 6 Feb 2023 17:21:16 -0800 Subject: [PATCH 3/8] Split fn_ctxt/adjust_fulfillment_errors from fn_ctxt/checks --- .../src/fn_ctxt/adjust_fulfillment_errors.rs | 374 +++++++++++++++++- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 370 +---------------- 2 files changed, 374 insertions(+), 370 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs index 2eab68050d430..db1acb5992716 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs @@ -1,10 +1,382 @@ use crate::FnCtxt; use rustc_hir as hir; use rustc_hir::def::Res; -use rustc_middle::ty::{self, DefIdTree, Ty}; +use rustc_hir::def_id::DefId; +use rustc_infer::traits::ObligationCauseCode; +use rustc_middle::ty::{self, DefIdTree, Ty, TypeSuperVisitable, TypeVisitable, TypeVisitor}; +use rustc_span::{self, Span}; use rustc_trait_selection::traits; +use std::ops::ControlFlow; + impl<'a, 'tcx> FnCtxt<'a, 'tcx> { + pub fn adjust_fulfillment_error_for_expr_obligation( + &self, + error: &mut traits::FulfillmentError<'tcx>, + ) -> bool { + let (traits::ExprItemObligation(def_id, hir_id, idx) | traits::ExprBindingObligation(def_id, _, hir_id, idx)) + = *error.obligation.cause.code().peel_derives() else { return false; }; + let hir = self.tcx.hir(); + let hir::Node::Expr(expr) = hir.get(hir_id) else { return false; }; + + let Some(unsubstituted_pred) = + self.tcx.predicates_of(def_id).instantiate_identity(self.tcx).predicates.into_iter().nth(idx) + else { return false; }; + + let generics = self.tcx.generics_of(def_id); + let predicate_substs = match unsubstituted_pred.kind().skip_binder() { + ty::PredicateKind::Clause(ty::Clause::Trait(pred)) => pred.trait_ref.substs, + ty::PredicateKind::Clause(ty::Clause::Projection(pred)) => pred.projection_ty.substs, + _ => ty::List::empty(), + }; + + let find_param_matching = |matches: &dyn Fn(&ty::ParamTy) -> bool| { + predicate_substs.types().find_map(|ty| { + ty.walk().find_map(|arg| { + if let ty::GenericArgKind::Type(ty) = arg.unpack() + && let ty::Param(param_ty) = ty.kind() + && matches(param_ty) + { + Some(arg) + } else { + None + } + }) + }) + }; + + // Prefer generics that are local to the fn item, since these are likely + // to be the cause of the unsatisfied predicate. + let mut param_to_point_at = find_param_matching(&|param_ty| { + self.tcx.parent(generics.type_param(param_ty, self.tcx).def_id) == def_id + }); + // Fall back to generic that isn't local to the fn item. This will come + // from a trait or impl, for example. + let mut fallback_param_to_point_at = find_param_matching(&|param_ty| { + self.tcx.parent(generics.type_param(param_ty, self.tcx).def_id) != def_id + && param_ty.name != rustc_span::symbol::kw::SelfUpper + }); + // Finally, the `Self` parameter is possibly the reason that the predicate + // is unsatisfied. This is less likely to be true for methods, because + // method probe means that we already kinda check that the predicates due + // to the `Self` type are true. + let mut self_param_to_point_at = + find_param_matching(&|param_ty| param_ty.name == rustc_span::symbol::kw::SelfUpper); + + // Finally, for ambiguity-related errors, we actually want to look + // for a parameter that is the source of the inference type left + // over in this predicate. + if let traits::FulfillmentErrorCode::CodeAmbiguity = error.code { + fallback_param_to_point_at = None; + self_param_to_point_at = None; + param_to_point_at = + self.find_ambiguous_parameter_in(def_id, error.root_obligation.predicate); + } + + if self.closure_span_overlaps_error(error, expr.span) { + return false; + } + + match &expr.kind { + hir::ExprKind::Path(qpath) => { + if let hir::Node::Expr(hir::Expr { + kind: hir::ExprKind::Call(callee, args), + hir_id: call_hir_id, + span: call_span, + .. + }) = hir.get_parent(expr.hir_id) + && callee.hir_id == expr.hir_id + { + if self.closure_span_overlaps_error(error, *call_span) { + return false; + } + + for param in + [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at] + .into_iter() + .flatten() + { + if self.blame_specific_arg_if_possible( + error, + def_id, + param, + *call_hir_id, + callee.span, + None, + args, + ) + { + return true; + } + } + } + // Notably, we only point to params that are local to the + // item we're checking, since those are the ones we are able + // to look in the final `hir::PathSegment` for. Everything else + // would require a deeper search into the `qpath` than I think + // is worthwhile. + if let Some(param_to_point_at) = param_to_point_at + && self.point_at_path_if_possible(error, def_id, param_to_point_at, qpath) + { + return true; + } + } + hir::ExprKind::MethodCall(segment, receiver, args, ..) => { + for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at] + .into_iter() + .flatten() + { + if self.blame_specific_arg_if_possible( + error, + def_id, + param, + hir_id, + segment.ident.span, + Some(receiver), + args, + ) { + return true; + } + } + if let Some(param_to_point_at) = param_to_point_at + && self.point_at_generic_if_possible(error, def_id, param_to_point_at, segment) + { + return true; + } + } + hir::ExprKind::Struct(qpath, fields, ..) => { + if let Res::Def( + hir::def::DefKind::Struct | hir::def::DefKind::Variant, + variant_def_id, + ) = self.typeck_results.borrow().qpath_res(qpath, hir_id) + { + for param in + [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at] + { + if let Some(param) = param { + let refined_expr = self.point_at_field_if_possible( + def_id, + param, + variant_def_id, + fields, + ); + + match refined_expr { + None => {} + Some((refined_expr, _)) => { + error.obligation.cause.span = refined_expr + .span + .find_ancestor_in_same_ctxt(error.obligation.cause.span) + .unwrap_or(refined_expr.span); + return true; + } + } + } + } + } + if let Some(param_to_point_at) = param_to_point_at + && self.point_at_path_if_possible(error, def_id, param_to_point_at, qpath) + { + return true; + } + } + _ => {} + } + + false + } + + fn point_at_path_if_possible( + &self, + error: &mut traits::FulfillmentError<'tcx>, + def_id: DefId, + param: ty::GenericArg<'tcx>, + qpath: &hir::QPath<'tcx>, + ) -> bool { + match qpath { + hir::QPath::Resolved(_, path) => { + if let Some(segment) = path.segments.last() + && self.point_at_generic_if_possible(error, def_id, param, segment) + { + return true; + } + } + hir::QPath::TypeRelative(_, segment) => { + if self.point_at_generic_if_possible(error, def_id, param, segment) { + return true; + } + } + _ => {} + } + + false + } + + fn point_at_generic_if_possible( + &self, + error: &mut traits::FulfillmentError<'tcx>, + def_id: DefId, + param_to_point_at: ty::GenericArg<'tcx>, + segment: &hir::PathSegment<'tcx>, + ) -> bool { + let own_substs = self + .tcx + .generics_of(def_id) + .own_substs(ty::InternalSubsts::identity_for_item(self.tcx, def_id)); + let Some((index, _)) = own_substs + .iter() + .filter(|arg| matches!(arg.unpack(), ty::GenericArgKind::Type(_))) + .enumerate() + .find(|(_, arg)| **arg == param_to_point_at) else { return false }; + let Some(arg) = segment + .args() + .args + .iter() + .filter(|arg| matches!(arg, hir::GenericArg::Type(_))) + .nth(index) else { return false; }; + error.obligation.cause.span = arg + .span() + .find_ancestor_in_same_ctxt(error.obligation.cause.span) + .unwrap_or(arg.span()); + true + } + + fn find_ambiguous_parameter_in>( + &self, + item_def_id: DefId, + t: T, + ) -> Option> { + struct FindAmbiguousParameter<'a, 'tcx>(&'a FnCtxt<'a, 'tcx>, DefId); + impl<'tcx> TypeVisitor<'tcx> for FindAmbiguousParameter<'_, 'tcx> { + type BreakTy = ty::GenericArg<'tcx>; + fn visit_ty(&mut self, ty: Ty<'tcx>) -> std::ops::ControlFlow { + if let Some(origin) = self.0.type_var_origin(ty) + && let rustc_infer::infer::type_variable::TypeVariableOriginKind::TypeParameterDefinition(_, Some(def_id)) = + origin.kind + && let generics = self.0.tcx.generics_of(self.1) + && let Some(index) = generics.param_def_id_to_index(self.0.tcx, def_id) + && let Some(subst) = ty::InternalSubsts::identity_for_item(self.0.tcx, self.1) + .get(index as usize) + { + ControlFlow::Break(*subst) + } else { + ty.super_visit_with(self) + } + } + } + t.visit_with(&mut FindAmbiguousParameter(self, item_def_id)).break_value() + } + + fn closure_span_overlaps_error( + &self, + error: &traits::FulfillmentError<'tcx>, + span: Span, + ) -> bool { + if let traits::FulfillmentErrorCode::CodeSelectionError( + traits::SelectionError::OutputTypeParameterMismatch(_, expected, _), + ) = error.code + && let ty::Closure(def_id, _) | ty::Generator(def_id, ..) = expected.skip_binder().self_ty().kind() + && span.overlaps(self.tcx.def_span(*def_id)) + { + true + } else { + false + } + } + + fn point_at_field_if_possible( + &self, + def_id: DefId, + param_to_point_at: ty::GenericArg<'tcx>, + variant_def_id: DefId, + expr_fields: &[hir::ExprField<'tcx>], + ) -> Option<(&'tcx hir::Expr<'tcx>, Ty<'tcx>)> { + let def = self.tcx.adt_def(def_id); + + let identity_substs = ty::InternalSubsts::identity_for_item(self.tcx, def_id); + let fields_referencing_param: Vec<_> = def + .variant_with_id(variant_def_id) + .fields + .iter() + .filter(|field| { + let field_ty = field.ty(self.tcx, identity_substs); + Self::find_param_in_ty(field_ty.into(), param_to_point_at) + }) + .collect(); + + if let [field] = fields_referencing_param.as_slice() { + for expr_field in expr_fields { + // Look for the ExprField that matches the field, using the + // same rules that check_expr_struct uses for macro hygiene. + if self.tcx.adjust_ident(expr_field.ident, variant_def_id) == field.ident(self.tcx) + { + return Some((expr_field.expr, self.tcx.type_of(field.did))); + } + } + } + + None + } + + /// - `blame_specific_*` means that the function will recursively traverse the expression, + /// looking for the most-specific-possible span to blame. + /// + /// - `point_at_*` means that the function will only go "one level", pointing at the specific + /// expression mentioned. + /// + /// `blame_specific_arg_if_possible` will find the most-specific expression anywhere inside + /// the provided function call expression, and mark it as responsible for the fullfillment + /// error. + fn blame_specific_arg_if_possible( + &self, + error: &mut traits::FulfillmentError<'tcx>, + def_id: DefId, + param_to_point_at: ty::GenericArg<'tcx>, + call_hir_id: hir::HirId, + callee_span: Span, + receiver: Option<&'tcx hir::Expr<'tcx>>, + args: &'tcx [hir::Expr<'tcx>], + ) -> bool { + let ty = self.tcx.type_of(def_id); + if !ty.is_fn() { + return false; + } + let sig = ty.fn_sig(self.tcx).skip_binder(); + let args_referencing_param: Vec<_> = sig + .inputs() + .iter() + .enumerate() + .filter(|(_, ty)| Self::find_param_in_ty((**ty).into(), param_to_point_at)) + .collect(); + // If there's one field that references the given generic, great! + if let [(idx, _)] = args_referencing_param.as_slice() + && let Some(arg) = receiver + .map_or(args.get(*idx), |rcvr| if *idx == 0 { Some(rcvr) } else { args.get(*idx - 1) }) { + + error.obligation.cause.span = arg.span.find_ancestor_in_same_ctxt(error.obligation.cause.span).unwrap_or(arg.span); + + if let hir::Node::Expr(arg_expr) = self.tcx.hir().get(arg.hir_id) { + // This is more specific than pointing at the entire argument. + self.blame_specific_expr_if_possible(error, arg_expr) + } + + error.obligation.cause.map_code(|parent_code| { + ObligationCauseCode::FunctionArgumentObligation { + arg_hir_id: arg.hir_id, + call_hir_id, + parent_code, + } + }); + return true; + } else if args_referencing_param.len() > 0 { + // If more than one argument applies, then point to the callee span at least... + // We have chance to fix this up further in `point_at_generics_if_possible` + error.obligation.cause.span = callee_span; + } + + false + } + /** * Recursively searches for the most-specific blamable expression. * For example, if you have a chain of constraints like: diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 1055ee953eae6..2a1265600de8b 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -26,7 +26,7 @@ use rustc_infer::infer::InferOk; use rustc_infer::infer::TypeTrace; use rustc_middle::ty::adjustment::AllowTwoPhase; use rustc_middle::ty::visit::TypeVisitable; -use rustc_middle::ty::{self, DefIdTree, IsSuggestable, Ty, TypeSuperVisitable, TypeVisitor}; +use rustc_middle::ty::{self, DefIdTree, IsSuggestable, Ty}; use rustc_session::Session; use rustc_span::symbol::{kw, Ident}; use rustc_span::{self, sym, Span}; @@ -36,8 +36,6 @@ use std::iter; use std::mem; use std::slice; -use std::ops::ControlFlow; - impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub(in super::super) fn check_casts(&mut self) { // don't hold the borrow to deferred_cast_checks while checking to avoid borrow checker errors @@ -1758,372 +1756,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - fn adjust_fulfillment_error_for_expr_obligation( - &self, - error: &mut traits::FulfillmentError<'tcx>, - ) -> bool { - let (traits::ExprItemObligation(def_id, hir_id, idx) | traits::ExprBindingObligation(def_id, _, hir_id, idx)) - = *error.obligation.cause.code().peel_derives() else { return false; }; - let hir = self.tcx.hir(); - let hir::Node::Expr(expr) = hir.get(hir_id) else { return false; }; - - let Some(unsubstituted_pred) = - self.tcx.predicates_of(def_id).instantiate_identity(self.tcx).predicates.into_iter().nth(idx) - else { return false; }; - - let generics = self.tcx.generics_of(def_id); - let predicate_substs = match unsubstituted_pred.kind().skip_binder() { - ty::PredicateKind::Clause(ty::Clause::Trait(pred)) => pred.trait_ref.substs, - ty::PredicateKind::Clause(ty::Clause::Projection(pred)) => pred.projection_ty.substs, - _ => ty::List::empty(), - }; - - let find_param_matching = |matches: &dyn Fn(&ty::ParamTy) -> bool| { - predicate_substs.types().find_map(|ty| { - ty.walk().find_map(|arg| { - if let ty::GenericArgKind::Type(ty) = arg.unpack() - && let ty::Param(param_ty) = ty.kind() - && matches(param_ty) - { - Some(arg) - } else { - None - } - }) - }) - }; - - // Prefer generics that are local to the fn item, since these are likely - // to be the cause of the unsatisfied predicate. - let mut param_to_point_at = find_param_matching(&|param_ty| { - self.tcx.parent(generics.type_param(param_ty, self.tcx).def_id) == def_id - }); - // Fall back to generic that isn't local to the fn item. This will come - // from a trait or impl, for example. - let mut fallback_param_to_point_at = find_param_matching(&|param_ty| { - self.tcx.parent(generics.type_param(param_ty, self.tcx).def_id) != def_id - && param_ty.name != rustc_span::symbol::kw::SelfUpper - }); - // Finally, the `Self` parameter is possibly the reason that the predicate - // is unsatisfied. This is less likely to be true for methods, because - // method probe means that we already kinda check that the predicates due - // to the `Self` type are true. - let mut self_param_to_point_at = - find_param_matching(&|param_ty| param_ty.name == rustc_span::symbol::kw::SelfUpper); - - // Finally, for ambiguity-related errors, we actually want to look - // for a parameter that is the source of the inference type left - // over in this predicate. - if let traits::FulfillmentErrorCode::CodeAmbiguity = error.code { - fallback_param_to_point_at = None; - self_param_to_point_at = None; - param_to_point_at = - self.find_ambiguous_parameter_in(def_id, error.root_obligation.predicate); - } - - if self.closure_span_overlaps_error(error, expr.span) { - return false; - } - - match &expr.kind { - hir::ExprKind::Path(qpath) => { - if let hir::Node::Expr(hir::Expr { - kind: hir::ExprKind::Call(callee, args), - hir_id: call_hir_id, - span: call_span, - .. - }) = hir.get_parent(expr.hir_id) - && callee.hir_id == expr.hir_id - { - if self.closure_span_overlaps_error(error, *call_span) { - return false; - } - - for param in - [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at] - .into_iter() - .flatten() - { - if self.blame_specific_arg_if_possible( - error, - def_id, - param, - *call_hir_id, - callee.span, - None, - args, - ) - { - return true; - } - } - } - // Notably, we only point to params that are local to the - // item we're checking, since those are the ones we are able - // to look in the final `hir::PathSegment` for. Everything else - // would require a deeper search into the `qpath` than I think - // is worthwhile. - if let Some(param_to_point_at) = param_to_point_at - && self.point_at_path_if_possible(error, def_id, param_to_point_at, qpath) - { - return true; - } - } - hir::ExprKind::MethodCall(segment, receiver, args, ..) => { - for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at] - .into_iter() - .flatten() - { - if self.blame_specific_arg_if_possible( - error, - def_id, - param, - hir_id, - segment.ident.span, - Some(receiver), - args, - ) { - return true; - } - } - if let Some(param_to_point_at) = param_to_point_at - && self.point_at_generic_if_possible(error, def_id, param_to_point_at, segment) - { - return true; - } - } - hir::ExprKind::Struct(qpath, fields, ..) => { - if let Res::Def(DefKind::Struct | DefKind::Variant, variant_def_id) = - self.typeck_results.borrow().qpath_res(qpath, hir_id) - { - for param in - [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at] - { - if let Some(param) = param { - let refined_expr = self.point_at_field_if_possible( - def_id, - param, - variant_def_id, - fields, - ); - - match refined_expr { - None => {} - Some((refined_expr, _)) => { - error.obligation.cause.span = refined_expr - .span - .find_ancestor_in_same_ctxt(error.obligation.cause.span) - .unwrap_or(refined_expr.span); - return true; - } - } - } - } - } - if let Some(param_to_point_at) = param_to_point_at - && self.point_at_path_if_possible(error, def_id, param_to_point_at, qpath) - { - return true; - } - } - _ => {} - } - - false - } - - fn closure_span_overlaps_error( - &self, - error: &traits::FulfillmentError<'tcx>, - span: Span, - ) -> bool { - if let traits::FulfillmentErrorCode::CodeSelectionError( - traits::SelectionError::OutputTypeParameterMismatch(_, expected, _), - ) = error.code - && let ty::Closure(def_id, _) | ty::Generator(def_id, ..) = expected.skip_binder().self_ty().kind() - && span.overlaps(self.tcx.def_span(*def_id)) - { - true - } else { - false - } - } - - /// - `blame_specific_*` means that the function will recursively traverse the expression, - /// looking for the most-specific-possible span to blame. - /// - /// - `point_at_*` means that the function will only go "one level", pointing at the specific - /// expression mentioned. - /// - /// `blame_specific_arg_if_possible` will find the most-specific expression anywhere inside - /// the provided function call expression, and mark it as responsible for the fullfillment - /// error. - fn blame_specific_arg_if_possible( - &self, - error: &mut traits::FulfillmentError<'tcx>, - def_id: DefId, - param_to_point_at: ty::GenericArg<'tcx>, - call_hir_id: hir::HirId, - callee_span: Span, - receiver: Option<&'tcx hir::Expr<'tcx>>, - args: &'tcx [hir::Expr<'tcx>], - ) -> bool { - let ty = self.tcx.type_of(def_id); - if !ty.is_fn() { - return false; - } - let sig = ty.fn_sig(self.tcx).skip_binder(); - let args_referencing_param: Vec<_> = sig - .inputs() - .iter() - .enumerate() - .filter(|(_, ty)| Self::find_param_in_ty((**ty).into(), param_to_point_at)) - .collect(); - // If there's one field that references the given generic, great! - if let [(idx, _)] = args_referencing_param.as_slice() - && let Some(arg) = receiver - .map_or(args.get(*idx), |rcvr| if *idx == 0 { Some(rcvr) } else { args.get(*idx - 1) }) { - - error.obligation.cause.span = arg.span.find_ancestor_in_same_ctxt(error.obligation.cause.span).unwrap_or(arg.span); - - if let hir::Node::Expr(arg_expr) = self.tcx.hir().get(arg.hir_id) { - // This is more specific than pointing at the entire argument. - self.blame_specific_expr_if_possible(error, arg_expr) - } - - error.obligation.cause.map_code(|parent_code| { - ObligationCauseCode::FunctionArgumentObligation { - arg_hir_id: arg.hir_id, - call_hir_id, - parent_code, - } - }); - return true; - } else if args_referencing_param.len() > 0 { - // If more than one argument applies, then point to the callee span at least... - // We have chance to fix this up further in `point_at_generics_if_possible` - error.obligation.cause.span = callee_span; - } - - false - } - - // FIXME: Make this private and move to mod adjust_fulfillment_errors - pub fn point_at_field_if_possible( - &self, - def_id: DefId, - param_to_point_at: ty::GenericArg<'tcx>, - variant_def_id: DefId, - expr_fields: &[hir::ExprField<'tcx>], - ) -> Option<(&'tcx hir::Expr<'tcx>, Ty<'tcx>)> { - let def = self.tcx.adt_def(def_id); - - let identity_substs = ty::InternalSubsts::identity_for_item(self.tcx, def_id); - let fields_referencing_param: Vec<_> = def - .variant_with_id(variant_def_id) - .fields - .iter() - .filter(|field| { - let field_ty = field.ty(self.tcx, identity_substs); - Self::find_param_in_ty(field_ty.into(), param_to_point_at) - }) - .collect(); - - if let [field] = fields_referencing_param.as_slice() { - for expr_field in expr_fields { - // Look for the ExprField that matches the field, using the - // same rules that check_expr_struct uses for macro hygiene. - if self.tcx.adjust_ident(expr_field.ident, variant_def_id) == field.ident(self.tcx) - { - return Some((expr_field.expr, self.tcx.type_of(field.did))); - } - } - } - - None - } - - fn point_at_path_if_possible( - &self, - error: &mut traits::FulfillmentError<'tcx>, - def_id: DefId, - param: ty::GenericArg<'tcx>, - qpath: &QPath<'tcx>, - ) -> bool { - match qpath { - hir::QPath::Resolved(_, path) => { - if let Some(segment) = path.segments.last() - && self.point_at_generic_if_possible(error, def_id, param, segment) - { - return true; - } - } - hir::QPath::TypeRelative(_, segment) => { - if self.point_at_generic_if_possible(error, def_id, param, segment) { - return true; - } - } - _ => {} - } - - false - } - - fn point_at_generic_if_possible( - &self, - error: &mut traits::FulfillmentError<'tcx>, - def_id: DefId, - param_to_point_at: ty::GenericArg<'tcx>, - segment: &hir::PathSegment<'tcx>, - ) -> bool { - let own_substs = self - .tcx - .generics_of(def_id) - .own_substs(ty::InternalSubsts::identity_for_item(self.tcx, def_id)); - let Some((index, _)) = own_substs - .iter() - .filter(|arg| matches!(arg.unpack(), ty::GenericArgKind::Type(_))) - .enumerate() - .find(|(_, arg)| **arg == param_to_point_at) else { return false }; - let Some(arg) = segment - .args() - .args - .iter() - .filter(|arg| matches!(arg, hir::GenericArg::Type(_))) - .nth(index) else { return false; }; - error.obligation.cause.span = arg - .span() - .find_ancestor_in_same_ctxt(error.obligation.cause.span) - .unwrap_or(arg.span()); - true - } - - fn find_ambiguous_parameter_in>( - &self, - item_def_id: DefId, - t: T, - ) -> Option> { - struct FindAmbiguousParameter<'a, 'tcx>(&'a FnCtxt<'a, 'tcx>, DefId); - impl<'tcx> TypeVisitor<'tcx> for FindAmbiguousParameter<'_, 'tcx> { - type BreakTy = ty::GenericArg<'tcx>; - fn visit_ty(&mut self, ty: Ty<'tcx>) -> std::ops::ControlFlow { - if let Some(origin) = self.0.type_var_origin(ty) - && let TypeVariableOriginKind::TypeParameterDefinition(_, Some(def_id)) = - origin.kind - && let generics = self.0.tcx.generics_of(self.1) - && let Some(index) = generics.param_def_id_to_index(self.0.tcx, def_id) - && let Some(subst) = ty::InternalSubsts::identity_for_item(self.0.tcx, self.1) - .get(index as usize) - { - ControlFlow::Break(*subst) - } else { - ty.super_visit_with(self) - } - } - } - t.visit_with(&mut FindAmbiguousParameter(self, item_def_id)).break_value() - } - fn label_fn_like( &self, err: &mut Diagnostic, From 63dc0b86beb75bca4a2aa81f36f08bb3551c5d52 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Tue, 7 Feb 2023 04:41:13 +0200 Subject: [PATCH 4/8] allow quick-edit convenience --- src/doc/rustc/book.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/doc/rustc/book.toml b/src/doc/rustc/book.toml index 372350403e281..cea6033ede208 100644 --- a/src/doc/rustc/book.toml +++ b/src/doc/rustc/book.toml @@ -5,3 +5,4 @@ title = "The rustc book" [output.html] git-repository-url = "https://github.com/rust-lang/rust/tree/master/src/doc/rustc" +edit-url-template = "https://github.com/rust-lang/rust/edit/master/src/doc/rustc/{path}" From a002c057263f170f24e2bf18590185ec3a47ff50 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Tue, 7 Feb 2023 04:54:01 +0200 Subject: [PATCH 5/8] make more readable --- src/doc/rustc/src/codegen-options/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md index 7e355b7fccfc4..1770c121a0e73 100644 --- a/src/doc/rustc/src/codegen-options/index.md +++ b/src/doc/rustc/src/codegen-options/index.md @@ -562,7 +562,7 @@ Supported values for this option are: * `v0` — The "v0" mangling scheme. The specific format is not specified at this time. -The default if not specified will use a compiler-chosen default which may +The default, if not specified, will use a compiler-chosen default which may change in the future. [name mangling]: https://en.wikipedia.org/wiki/Name_mangling From a04f31dc34d56b28f1a92800e4682941c8bc41ec Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 7 Feb 2023 10:59:18 +0100 Subject: [PATCH 6/8] remove binder from query constraints --- .../src/type_check/constraint_conversion.rs | 12 +----- .../src/infer/canonical/query_response.rs | 41 ++++++++----------- compiler/rustc_middle/src/infer/canonical.rs | 6 +-- 3 files changed, 20 insertions(+), 39 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs index e15d1b99ad205..1dc6c42fbf78e 100644 --- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs +++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs @@ -83,16 +83,8 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { } self.constraints.member_constraints = tmp; - for (predicate, constraint_category) in outlives { - // At the moment, we never generate any "higher-ranked" - // region constraints like `for<'a> 'a: 'b`. At some point - // when we move to universes, we will, and this assertion - // will start to fail. - let predicate = predicate.no_bound_vars().unwrap_or_else(|| { - bug!("query_constraint {:?} contained bound vars", predicate,); - }); - - self.convert(predicate, *constraint_category); + for &(predicate, constraint_category) in outlives { + self.convert(predicate, constraint_category); } } diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index 3e8e7734a5a5d..7cc9e49b1b62a 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -268,14 +268,12 @@ impl<'tcx> InferCtxt<'tcx> { (GenericArgKind::Lifetime(v_o), GenericArgKind::Lifetime(v_r)) => { // To make `v_o = v_r`, we emit `v_o: v_r` and `v_r: v_o`. if v_o != v_r { - output_query_region_constraints.outlives.push(( - ty::Binder::dummy(ty::OutlivesPredicate(v_o.into(), v_r)), - constraint_category, - )); - output_query_region_constraints.outlives.push(( - ty::Binder::dummy(ty::OutlivesPredicate(v_r.into(), v_o)), - constraint_category, - )); + output_query_region_constraints + .outlives + .push((ty::OutlivesPredicate(v_o.into(), v_r), constraint_category)); + output_query_region_constraints + .outlives + .push((ty::OutlivesPredicate(v_r.into(), v_o), constraint_category)); } } @@ -318,10 +316,8 @@ impl<'tcx> InferCtxt<'tcx> { query_response.value.region_constraints.outlives.iter().filter_map(|&r_c| { let r_c = substitute_value(self.tcx, &result_subst, r_c); - // Screen out `'a: 'a` cases -- we skip the binder here but - // only compare the inner values to one another, so they are still at - // consistent binding levels. - let ty::OutlivesPredicate(k1, r2) = r_c.0.skip_binder(); + // Screen out `'a: 'a` cases. + let ty::OutlivesPredicate(k1, r2) = r_c.0; if k1 != r2.into() { Some(r_c) } else { None } }), ); @@ -559,11 +555,11 @@ impl<'tcx> InferCtxt<'tcx> { pub fn query_outlives_constraint_to_obligation( &self, - predicate: QueryOutlivesConstraint<'tcx>, + (predicate, _): QueryOutlivesConstraint<'tcx>, cause: ObligationCause<'tcx>, param_env: ty::ParamEnv<'tcx>, ) -> Obligation<'tcx, ty::Predicate<'tcx>> { - let ty::OutlivesPredicate(k1, r2) = predicate.0.skip_binder(); + let ty::OutlivesPredicate(k1, r2) = predicate; let atom = match k1.unpack() { GenericArgKind::Lifetime(r1) => { @@ -578,7 +574,7 @@ impl<'tcx> InferCtxt<'tcx> { span_bug!(cause.span, "unexpected const outlives {:?}", predicate); } }; - let predicate = predicate.0.rebind(atom); + let predicate = ty::Binder::dummy(atom); Obligation::new(self.tcx, cause, param_env, predicate) } @@ -643,8 +639,7 @@ pub fn make_query_region_constraints<'tcx>( let outlives: Vec<_> = constraints .iter() .map(|(k, origin)| { - // no bound vars in the code above - let constraint = ty::Binder::dummy(match *k { + let constraint = match *k { // Swap regions because we are going from sub (<=) to outlives // (>=). Constraint::VarSubVar(v1, v2) => ty::OutlivesPredicate( @@ -658,16 +653,12 @@ pub fn make_query_region_constraints<'tcx>( ty::OutlivesPredicate(tcx.mk_region(ty::ReVar(v2)).into(), r1) } Constraint::RegSubReg(r1, r2) => ty::OutlivesPredicate(r2.into(), r1), - }); + }; (constraint, origin.to_constraint_category()) }) - .chain( - outlives_obligations - // no bound vars in the code above - .map(|(ty, r, constraint_category)| { - (ty::Binder::dummy(ty::OutlivesPredicate(ty.into(), r)), constraint_category) - }), - ) + .chain(outlives_obligations.map(|(ty, r, constraint_category)| { + (ty::OutlivesPredicate(ty.into(), r), constraint_category) + })) .collect(); QueryRegionConstraints { outlives, member_constraints: member_constraints.clone() } diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs index 6e130bbf7d828..d6f20a8fc06ec 100644 --- a/compiler/rustc_middle/src/infer/canonical.rs +++ b/compiler/rustc_middle/src/infer/canonical.rs @@ -324,10 +324,8 @@ impl<'tcx, V> Canonical<'tcx, V> { } } -pub type QueryOutlivesConstraint<'tcx> = ( - ty::Binder<'tcx, ty::OutlivesPredicate, Region<'tcx>>>, - ConstraintCategory<'tcx>, -); +pub type QueryOutlivesConstraint<'tcx> = + (ty::OutlivesPredicate, Region<'tcx>>, ConstraintCategory<'tcx>); TrivialTypeTraversalAndLiftImpls! { for <'tcx> { From 2900ba15b3f2b17808b32af050c85f86ca98c136 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 7 Feb 2023 11:39:07 +0100 Subject: [PATCH 7/8] miri: fix ICE when running out of address space --- .../interpret/intrinsics/caller_location.rs | 7 ++-- .../rustc_const_eval/src/interpret/machine.rs | 6 ++-- .../rustc_const_eval/src/interpret/memory.rs | 12 +++---- .../rustc_const_eval/src/interpret/place.rs | 6 ++-- .../rustc_middle/src/mir/interpret/error.rs | 7 +++- src/tools/miri/src/intptrcast.rs | 35 ++++++++++++++----- src/tools/miri/src/machine.rs | 8 ++--- src/tools/miri/src/shims/backtrace.rs | 4 +-- src/tools/miri/src/shims/panic.rs | 2 +- 9 files changed, 54 insertions(+), 33 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs b/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs index 77c7b4bacb8c8..5042c6bac9932 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs @@ -78,13 +78,16 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { col: u32, ) -> MPlaceTy<'tcx, M::Provenance> { let loc_details = &self.tcx.sess.opts.unstable_opts.location_detail; + // This can fail if rustc runs out of memory right here. Trying to emit an error would be + // pointless, since that would require allocating more memory than these short strings. let file = if loc_details.file { self.allocate_str(filename.as_str(), MemoryKind::CallerLocation, Mutability::Not) + .unwrap() } else { // FIXME: This creates a new allocation each time. It might be preferable to // perform this allocation only once, and re-use the `MPlaceTy`. // See https://github.com/rust-lang/rust/pull/89920#discussion_r730012398 - self.allocate_str("", MemoryKind::CallerLocation, Mutability::Not) + self.allocate_str("", MemoryKind::CallerLocation, Mutability::Not).unwrap() }; let line = if loc_details.line { Scalar::from_u32(line) } else { Scalar::from_u32(0) }; let col = if loc_details.column { Scalar::from_u32(col) } else { Scalar::from_u32(0) }; @@ -95,8 +98,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { .bound_type_of(self.tcx.require_lang_item(LangItem::PanicLocation, None)) .subst(*self.tcx, self.tcx.mk_substs([self.tcx.lifetimes.re_erased.into()].iter())); let loc_layout = self.layout_of(loc_ty).unwrap(); - // This can fail if rustc runs out of memory right here. Trying to emit an error would be - // pointless, since that would require allocating more memory than a Location. let location = self.allocate(loc_layout, MemoryKind::CallerLocation).unwrap(); // Initialize fields. diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index 76ed7b80f8d81..d8087a36a7c6a 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -291,7 +291,7 @@ pub trait Machine<'mir, 'tcx>: Sized { fn adjust_alloc_base_pointer( ecx: &InterpCx<'mir, 'tcx, Self>, ptr: Pointer, - ) -> Pointer; + ) -> InterpResult<'tcx, Pointer>; /// "Int-to-pointer cast" fn ptr_from_addr_cast( @@ -505,8 +505,8 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) { fn adjust_alloc_base_pointer( _ecx: &InterpCx<$mir, $tcx, Self>, ptr: Pointer, - ) -> Pointer { - ptr + ) -> InterpResult<$tcx, Pointer> { + Ok(ptr) } #[inline(always)] diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index a87ce0053e8a0..cfad930b1e52e 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -171,7 +171,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { _ => {} } // And we need to get the provenance. - Ok(M::adjust_alloc_base_pointer(self, ptr)) + M::adjust_alloc_base_pointer(self, ptr) } pub fn create_fn_alloc_ptr( @@ -200,8 +200,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { kind: MemoryKind, ) -> InterpResult<'tcx, Pointer> { let alloc = Allocation::uninit(size, align, M::PANIC_ON_ALLOC_FAIL)?; - // We can `unwrap` since `alloc` contains no pointers. - Ok(self.allocate_raw_ptr(alloc, kind).unwrap()) + self.allocate_raw_ptr(alloc, kind) } pub fn allocate_bytes_ptr( @@ -210,10 +209,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { align: Align, kind: MemoryKind, mutability: Mutability, - ) -> Pointer { + ) -> InterpResult<'tcx, Pointer> { let alloc = Allocation::from_bytes(bytes, align, mutability); - // We can `unwrap` since `alloc` contains no pointers. - self.allocate_raw_ptr(alloc, kind).unwrap() + self.allocate_raw_ptr(alloc, kind) } /// This can fail only of `alloc` contains provenance. @@ -230,7 +228,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ); let alloc = M::adjust_allocation(self, id, Cow::Owned(alloc), Some(kind))?; self.memory.alloc_map.insert(id, (kind, alloc.into_owned())); - Ok(M::adjust_alloc_base_pointer(self, Pointer::from(id))) + M::adjust_alloc_base_pointer(self, Pointer::from(id)) } pub fn reallocate_ptr( diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 8d4d0420cda4a..86786d812667f 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -754,8 +754,8 @@ where str: &str, kind: MemoryKind, mutbl: Mutability, - ) -> MPlaceTy<'tcx, M::Provenance> { - let ptr = self.allocate_bytes_ptr(str.as_bytes(), Align::ONE, kind, mutbl); + ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::Provenance>> { + let ptr = self.allocate_bytes_ptr(str.as_bytes(), Align::ONE, kind, mutbl)?; let meta = Scalar::from_machine_usize(u64::try_from(str.len()).unwrap(), self); let mplace = MemPlace { ptr: ptr.into(), meta: MemPlaceMeta::Meta(meta) }; @@ -764,7 +764,7 @@ where ty::TypeAndMut { ty: self.tcx.types.str_, mutbl }, ); let layout = self.layout_of(ty).unwrap(); - MPlaceTy { mplace, layout, align: layout.align.abi } + Ok(MPlaceTy { mplace, layout, align: layout.align.abi }) } /// Writes the discriminant of the given variant. diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index bd9cd53e11578..f22c0dbc60d9d 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -430,8 +430,10 @@ pub enum ResourceExhaustionInfo { /// /// The exact limit is set by the `const_eval_limit` attribute. StepLimitReached, - /// There is not enough memory to perform an allocation. + /// There is not enough memory (on the host) to perform an allocation. MemoryExhausted, + /// The address space (of the target) is full. + AddressSpaceFull, } impl fmt::Display for ResourceExhaustionInfo { @@ -447,6 +449,9 @@ impl fmt::Display for ResourceExhaustionInfo { MemoryExhausted => { write!(f, "tried to allocate more memory than available to compiler") } + AddressSpaceFull => { + write!(f, "there are no more free addresses in the address space") + } } } } diff --git a/src/tools/miri/src/intptrcast.rs b/src/tools/miri/src/intptrcast.rs index 618cf9df7f3f0..dcb1879042041 100644 --- a/src/tools/miri/src/intptrcast.rs +++ b/src/tools/miri/src/intptrcast.rs @@ -162,11 +162,14 @@ impl<'mir, 'tcx> GlobalStateInner { Ok(Pointer::new(Some(Provenance::Wildcard), Size::from_bytes(addr))) } - fn alloc_base_addr(ecx: &MiriInterpCx<'mir, 'tcx>, alloc_id: AllocId) -> u64 { + fn alloc_base_addr( + ecx: &MiriInterpCx<'mir, 'tcx>, + alloc_id: AllocId, + ) -> InterpResult<'tcx, u64> { let mut global_state = ecx.machine.intptrcast.borrow_mut(); let global_state = &mut *global_state; - match global_state.base_addr.entry(alloc_id) { + Ok(match global_state.base_addr.entry(alloc_id) { Entry::Occupied(entry) => *entry.get(), Entry::Vacant(entry) => { // There is nothing wrong with a raw pointer being cast to an integer only after @@ -181,7 +184,10 @@ impl<'mir, 'tcx> GlobalStateInner { rng.gen_range(0..16) }; // From next_base_addr + slack, round up to adjust for alignment. - let base_addr = global_state.next_base_addr.checked_add(slack).unwrap(); + let base_addr = global_state + .next_base_addr + .checked_add(slack) + .ok_or_else(|| err_exhaust!(AddressSpaceFull))?; let base_addr = Self::align_addr(base_addr, align.bytes()); entry.insert(base_addr); trace!( @@ -197,24 +203,33 @@ impl<'mir, 'tcx> GlobalStateInner { // of at least 1 to avoid two allocations having the same base address. // (The logic in `alloc_id_from_addr` assumes unique addresses, and different // function/vtable pointers need to be distinguishable!) - global_state.next_base_addr = base_addr.checked_add(max(size.bytes(), 1)).unwrap(); + global_state.next_base_addr = base_addr + .checked_add(max(size.bytes(), 1)) + .ok_or_else(|| err_exhaust!(AddressSpaceFull))?; + // Even if `Size` didn't overflow, we might still have filled up the address space. + if global_state.next_base_addr > ecx.machine_usize_max() { + throw_exhaust!(AddressSpaceFull); + } // Given that `next_base_addr` increases in each allocation, pushing the // corresponding tuple keeps `int_to_ptr_map` sorted global_state.int_to_ptr_map.push((base_addr, alloc_id)); base_addr } - } + }) } /// Convert a relative (tcx) pointer to an absolute address. - pub fn rel_ptr_to_addr(ecx: &MiriInterpCx<'mir, 'tcx>, ptr: Pointer) -> u64 { + pub fn rel_ptr_to_addr( + ecx: &MiriInterpCx<'mir, 'tcx>, + ptr: Pointer, + ) -> InterpResult<'tcx, u64> { let (alloc_id, offset) = ptr.into_parts(); // offset is relative (AllocId provenance) - let base_addr = GlobalStateInner::alloc_base_addr(ecx, alloc_id); + let base_addr = GlobalStateInner::alloc_base_addr(ecx, alloc_id)?; // Add offset with the right kind of pointer-overflowing arithmetic. let dl = ecx.data_layout(); - dl.overflowing_offset(base_addr, offset.bytes()).0 + Ok(dl.overflowing_offset(base_addr, offset.bytes()).0) } /// When a pointer is used for a memory access, this computes where in which allocation the @@ -232,7 +247,9 @@ impl<'mir, 'tcx> GlobalStateInner { GlobalStateInner::alloc_id_from_addr(ecx, addr.bytes())? }; - let base_addr = GlobalStateInner::alloc_base_addr(ecx, alloc_id); + // This cannot fail: since we already have a pointer with that provenance, rel_ptr_to_addr + // must have been called in the past. + let base_addr = GlobalStateInner::alloc_base_addr(ecx, alloc_id).unwrap(); // Wrapping "addr - base_addr" let dl = ecx.data_layout(); diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 01a3d7550e2e0..8e44d4d7adec8 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -971,7 +971,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { fn adjust_alloc_base_pointer( ecx: &MiriInterpCx<'mir, 'tcx>, ptr: Pointer, - ) -> Pointer { + ) -> InterpResult<'tcx, Pointer> { if cfg!(debug_assertions) { // The machine promises to never call us on thread-local or extern statics. let alloc_id = ptr.provenance; @@ -985,17 +985,17 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { _ => {} } } - let absolute_addr = intptrcast::GlobalStateInner::rel_ptr_to_addr(ecx, ptr); + let absolute_addr = intptrcast::GlobalStateInner::rel_ptr_to_addr(ecx, ptr)?; let tag = if let Some(borrow_tracker) = &ecx.machine.borrow_tracker { borrow_tracker.borrow_mut().base_ptr_tag(ptr.provenance, &ecx.machine) } else { // Value does not matter, SB is disabled BorTag::default() }; - Pointer::new( + Ok(Pointer::new( Provenance::Concrete { alloc_id: ptr.provenance, tag }, Size::from_bytes(absolute_addr), - ) + )) } #[inline(always)] diff --git a/src/tools/miri/src/shims/backtrace.rs b/src/tools/miri/src/shims/backtrace.rs index 15987eee537fd..ed1c6ebfece76 100644 --- a/src/tools/miri/src/shims/backtrace.rs +++ b/src/tools/miri/src/shims/backtrace.rs @@ -190,9 +190,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { 0 => { // These are "mutable" allocations as we consider them to be owned by the callee. let name_alloc = - this.allocate_str(&name, MiriMemoryKind::Rust.into(), Mutability::Mut); + this.allocate_str(&name, MiriMemoryKind::Rust.into(), Mutability::Mut)?; let filename_alloc = - this.allocate_str(&filename, MiriMemoryKind::Rust.into(), Mutability::Mut); + this.allocate_str(&filename, MiriMemoryKind::Rust.into(), Mutability::Mut)?; this.write_immediate( name_alloc.to_ref(this), diff --git a/src/tools/miri/src/shims/panic.rs b/src/tools/miri/src/shims/panic.rs index db3e42facadd0..0ea1137200b9d 100644 --- a/src/tools/miri/src/shims/panic.rs +++ b/src/tools/miri/src/shims/panic.rs @@ -172,7 +172,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let this = self.eval_context_mut(); // First arg: message. - let msg = this.allocate_str(msg, MiriMemoryKind::Machine.into(), Mutability::Not); + let msg = this.allocate_str(msg, MiriMemoryKind::Machine.into(), Mutability::Not)?; // Call the lang item. let panic = this.tcx.lang_items().panic_fn().unwrap(); From 147c51e17dfc6b22deb349297fc7d2bdad19cd4f Mon Sep 17 00:00:00 2001 From: Matthew Maurer Date: Tue, 7 Feb 2023 06:48:54 -0800 Subject: [PATCH 8/8] llvm-16: Use Triple.h from new header location. LLVM 16 has moved Triple.h from ADT and into TargetParser --- compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h b/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h index 727cfc4416ee9..9146a3739b2b1 100644 --- a/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h +++ b/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h @@ -4,7 +4,6 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/Triple.h" #include "llvm/Analysis/Lint.h" #include "llvm/Analysis/Passes.h" #include "llvm/IR/IRBuilder.h" @@ -44,6 +43,12 @@ #include "llvm/IR/IRPrintingPasses.h" #include "llvm/Linker/Linker.h" +#if LLVM_VERSION_GE(16, 0) +#include "llvm/TargetParser/Triple.h" +#else +#include "llvm/ADT/Triple.h" +#endif + extern "C" void LLVMRustSetLastError(const char *); enum class LLVMRustResult { Success, Failure };