diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index cc42e69f53827..4d1d208f91459 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -14,13 +14,14 @@ use rustc_hir as hir; use rustc_hir::def::Res; use rustc_hir::def_id::LocalDefId; use rustc_hir::{HirId, PatKind}; -use rustc_infer::infer::InferCtxt; use rustc_middle::hir::place::ProjectionKind; use rustc_middle::mir::FakeReadCause; +use rustc_middle::ty::BorrowKind::ImmBorrow; use rustc_middle::ty::{self, adjustment, AdtKind, Ty, TyCtxt}; use rustc_target::abi::FIRST_VARIANT; -use ty::BorrowKind::ImmBorrow; +use rustc_trait_selection::infer::InferCtxtExt; +use crate::fn_ctxt::FnCtxt; use crate::mem_categorization as mc; /// This trait defines the callbacks you can expect to receive when @@ -93,7 +94,6 @@ enum ConsumeMode { /// This is the code that actually walks the tree. pub struct ExprUseVisitor<'a, 'tcx> { mc: mc::MemCategorizationContext<'a, 'tcx>, - body_owner: LocalDefId, delegate: &'a mut dyn Delegate<'tcx>, } @@ -122,18 +122,12 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { /// - `delegate` -- who receives the callbacks /// - `param_env` --- parameter environment for trait lookups (esp. pertaining to `Copy`) /// - `typeck_results` --- typeck results for the code being analyzed - pub fn new( + pub(crate) fn new( delegate: &'a mut (dyn Delegate<'tcx> + 'a), - infcx: &'a InferCtxt<'tcx>, - body_owner: LocalDefId, - param_env: ty::ParamEnv<'tcx>, - typeck_results: &'a ty::TypeckResults<'tcx>, + fcx: &'a FnCtxt<'a, 'tcx>, + body_id: LocalDefId, ) -> Self { - ExprUseVisitor { - mc: mc::MemCategorizationContext::new(infcx, param_env, body_owner, typeck_results), - body_owner, - delegate, - } + ExprUseVisitor { mc: mc::MemCategorizationContext::new(fcx, body_id), delegate } } #[instrument(skip(self), level = "debug")] @@ -151,7 +145,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { } fn tcx(&self) -> TyCtxt<'tcx> { - self.mc.tcx() + self.mc.tcx } fn delegate_consume(&mut self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: HirId) { @@ -347,7 +341,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { } hir::ExprKind::AssignOp(_, lhs, rhs) => { - if self.mc.typeck_results.is_method_call(expr) { + if self.mc.typeck_results().is_method_call(expr) { self.consume_expr(lhs); } else { self.mutate_expr(lhs); @@ -398,7 +392,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { // discr does not necessarily need to be borrowed. // We only want to borrow discr if the pattern contain something other // than wildcards. - let ExprUseVisitor { ref mc, body_owner: _, delegate: _ } = *self; + let ExprUseVisitor { ref mc, delegate: _ } = *self; let mut needs_to_be_read = false; for pat in pats { mc.cat_pattern(discr_place.clone(), pat, |place, pat| { @@ -419,7 +413,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { // A `Path` pattern is just a name like `Foo`. This is either a // named constant or else it refers to an ADT variant - let res = self.mc.typeck_results.qpath_res(qpath, pat.hir_id); + let res = self.mc.typeck_results().qpath_res(qpath, pat.hir_id); match res { Res::Def(DefKind::Const, _) | Res::Def(DefKind::AssocConst, _) => { // Named constants have to be equated with the value @@ -545,7 +539,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { self.consume_expr(field.expr); // The struct path probably didn't resolve - if self.mc.typeck_results.opt_field_index(field.hir_id).is_none() { + if self.mc.typeck_results().opt_field_index(field.hir_id).is_none() { self.tcx().dcx().span_delayed_bug(field.span, "couldn't resolve index for field"); } } @@ -561,13 +555,13 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { // Select just those fields of the `with` // expression that will actually be used - match with_place.place.ty().kind() { + match self.mc.try_structurally_resolve_type(with_expr.span, with_place.place.ty()).kind() { ty::Adt(adt, args) if adt.is_struct() => { // Consume those fields of the with expression that are needed. for (f_index, with_field) in adt.non_enum_variant().fields.iter_enumerated() { - let is_mentioned = fields - .iter() - .any(|f| self.mc.typeck_results.opt_field_index(f.hir_id) == Some(f_index)); + let is_mentioned = fields.iter().any(|f| { + self.mc.typeck_results().opt_field_index(f.hir_id) == Some(f_index) + }); if !is_mentioned { let field_place = self.mc.cat_projection( &*with_expr, @@ -599,7 +593,8 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { /// consumed or borrowed as part of the automatic adjustment /// process. fn walk_adjustment(&mut self, expr: &hir::Expr<'_>) { - let adjustments = self.mc.typeck_results.expr_adjustments(expr); + let typeck_results = self.mc.typeck_results(); + let adjustments = typeck_results.expr_adjustments(expr); let mut place_with_id = return_if_err!(self.mc.cat_expr_unadjusted(expr)); for adjustment in adjustments { debug!("walk_adjustment expr={:?} adj={:?}", expr, adjustment); @@ -710,12 +705,12 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { debug!("walk_pat(discr_place={:?}, pat={:?}, has_guard={:?})", discr_place, pat, has_guard); let tcx = self.tcx(); - let ExprUseVisitor { ref mc, body_owner: _, ref mut delegate } = *self; + let ExprUseVisitor { ref mc, ref mut delegate } = *self; return_if_err!(mc.cat_pattern(discr_place.clone(), pat, |place, pat| { if let PatKind::Binding(_, canonical_id, ..) = pat.kind { debug!("walk_pat: binding place={:?} pat={:?}", place, pat); if let Some(bm) = - mc.typeck_results.extract_binding_mode(tcx.sess, pat.hir_id, pat.span) + mc.typeck_results().extract_binding_mode(tcx.sess, pat.hir_id, pat.span) { debug!("walk_pat: pat.hir_id={:?} bm={:?}", pat.hir_id, bm); @@ -755,7 +750,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { // determines whether to borrow *at the level of the deref pattern* rather than // borrowing the bound place (since that inner place is inside the temporary that // stores the result of calling `deref()`/`deref_mut()` so can't be captured). - let mutable = mc.typeck_results.pat_has_ref_mut_binding(subpattern); + let mutable = mc.typeck_results().pat_has_ref_mut_binding(subpattern); let mutability = if mutable { hir::Mutability::Mut } else { hir::Mutability::Not }; let bk = ty::BorrowKind::from_mutbl(mutability); delegate.borrow(place, discr_place.hir_id, bk); @@ -795,14 +790,14 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { let tcx = self.tcx(); let closure_def_id = closure_expr.def_id; - let upvars = tcx.upvars_mentioned(self.body_owner); + let upvars = tcx.upvars_mentioned(self.mc.inner_body_id); // For purposes of this function, coroutine and closures are equivalent. let body_owner_is_closure = - matches!(tcx.hir().body_owner_kind(self.body_owner), hir::BodyOwnerKind::Closure,); + matches!(tcx.hir().body_owner_kind(self.mc.inner_body_id), hir::BodyOwnerKind::Closure); // If we have a nested closure, we want to include the fake reads present in the nested closure. - if let Some(fake_reads) = self.mc.typeck_results.closure_fake_reads.get(&closure_def_id) { + if let Some(fake_reads) = self.mc.typeck_results().closure_fake_reads.get(&closure_def_id) { for (fake_read, cause, hir_id) in fake_reads.iter() { match fake_read.base { PlaceBase::Upvar(upvar_id) => { @@ -845,7 +840,8 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { } } - if let Some(min_captures) = self.mc.typeck_results.closure_min_captures.get(&closure_def_id) + if let Some(min_captures) = + self.mc.typeck_results().closure_min_captures.get(&closure_def_id) { for (var_hir_id, min_list) in min_captures.iter() { if upvars.map_or(body_owner_is_closure, |upvars| !upvars.contains_key(var_hir_id)) { @@ -860,7 +856,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { let place_base = if body_owner_is_closure { // Mark the place to be captured by the enclosing closure - PlaceBase::Upvar(ty::UpvarId::new(*var_hir_id, self.body_owner)) + PlaceBase::Upvar(ty::UpvarId::new(*var_hir_id, self.mc.inner_body_id)) } else { // If the body owner isn't a closure then the variable must // be a local variable @@ -898,7 +894,7 @@ fn copy_or_move<'a, 'tcx>( mc: &mc::MemCategorizationContext<'a, 'tcx>, place_with_id: &PlaceWithHirId<'tcx>, ) -> ConsumeMode { - if !mc.type_is_copy_modulo_regions(place_with_id.place.ty()) { + if !mc.type_is_copy_modulo_regions(mc.param_env, place_with_id.place.ty()) { ConsumeMode::Move } else { ConsumeMode::Copy diff --git a/compiler/rustc_hir_typeck/src/mem_categorization.rs b/compiler/rustc_hir_typeck/src/mem_categorization.rs index b44c2345933fb..8352d31682636 100644 --- a/compiler/rustc_hir_typeck/src/mem_categorization.rs +++ b/compiler/rustc_hir_typeck/src/mem_categorization.rs @@ -48,10 +48,12 @@ //! result of `*x'`, effectively, where `x'` is a `Categorization::Upvar` reference //! tied to `x`. The type of `x'` will be a borrowed pointer. +use std::cell::Ref; +use std::ops::Deref; + use rustc_middle::hir::place::*; use rustc_middle::ty::adjustment; -use rustc_middle::ty::fold::TypeFoldable; -use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{self, Ty, TypeVisitableExt}; use rustc_data_structures::fx::FxIndexMap; use rustc_hir as hir; @@ -59,10 +61,10 @@ use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::LocalDefId; use rustc_hir::pat_util::EnumerateAndAdjustIterator; use rustc_hir::{HirId, PatKind}; -use rustc_infer::infer::InferCtxt; use rustc_span::Span; use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT}; -use rustc_trait_selection::infer::InferCtxtExt; + +use crate::fn_ctxt::FnCtxt; pub(crate) trait HirNode { fn hir_id(&self) -> HirId; @@ -82,11 +84,19 @@ impl HirNode for hir::Pat<'_> { #[derive(Clone)] pub(crate) struct MemCategorizationContext<'a, 'tcx> { - pub(crate) typeck_results: &'a ty::TypeckResults<'tcx>, - infcx: &'a InferCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, - body_owner: LocalDefId, - upvars: Option<&'tcx FxIndexMap>, + pub fcx: &'a FnCtxt<'a, 'tcx>, + pub upvars: Option<&'tcx FxIndexMap>, + /// The def id of the body that is being categorized. + /// This is **different** from `fcx.body_id`. + pub inner_body_id: LocalDefId, +} + +impl<'a, 'tcx> Deref for MemCategorizationContext<'a, 'tcx> { + type Target = FnCtxt<'a, 'tcx>; + + fn deref(&self) -> &Self::Target { + self.fcx + } } pub(crate) type McResult = Result; @@ -94,71 +104,61 @@ pub(crate) type McResult = Result; impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { /// Creates a `MemCategorizationContext`. pub(crate) fn new( - infcx: &'a InferCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, - body_owner: LocalDefId, - typeck_results: &'a ty::TypeckResults<'tcx>, + fcx: &'a FnCtxt<'a, 'tcx>, + inner_body_id: LocalDefId, ) -> MemCategorizationContext<'a, 'tcx> { MemCategorizationContext { - typeck_results, - infcx, - param_env, - body_owner, - upvars: infcx.tcx.upvars_mentioned(body_owner), + fcx, + upvars: fcx.tcx.upvars_mentioned(inner_body_id), + inner_body_id, } } - pub(crate) fn tcx(&self) -> TyCtxt<'tcx> { - self.infcx.tcx - } - - pub(crate) fn type_is_copy_modulo_regions(&self, ty: Ty<'tcx>) -> bool { - self.infcx.type_is_copy_modulo_regions(self.param_env, ty) - } - - fn resolve_vars_if_possible(&self, value: T) -> T - where - T: TypeFoldable>, - { - self.infcx.resolve_vars_if_possible(value) - } - - fn is_tainted_by_errors(&self) -> bool { - self.infcx.tainted_by_errors().is_some() + pub(crate) fn typeck_results(&self) -> Ref<'a, ty::TypeckResults<'tcx>> { + self.fcx.typeck_results.borrow() } fn resolve_type_vars_or_error(&self, id: HirId, ty: Option>) -> McResult> { match ty { Some(ty) => { let ty = self.resolve_vars_if_possible(ty); - if ty.references_error() || ty.is_ty_var() { + if ty.references_error() { debug!("resolve_type_vars_or_error: error from {:?}", ty); Err(()) + } else if ty.is_ty_var() { + debug!("resolve_type_vars_or_error: infer var from {:?}", ty); + self.tcx + .dcx() + .span_delayed_bug(self.tcx.hir().span(id), "encountered type variable"); + Err(()) } else { Ok(ty) } } // FIXME - None if self.is_tainted_by_errors() => Err(()), + None if self.tainted_by_errors().is_some() => Err(()), None => { bug!( "no type for node {} in mem_categorization", - self.tcx().hir().node_to_string(id) + self.tcx.hir().node_to_string(id) ); } } } pub(crate) fn node_ty(&self, hir_id: HirId) -> McResult> { - self.resolve_type_vars_or_error(hir_id, self.typeck_results.node_type_opt(hir_id)) + self.resolve_type_vars_or_error(hir_id, self.typeck_results().node_type_opt(hir_id)) } fn expr_ty(&self, expr: &hir::Expr<'_>) -> McResult> { - self.resolve_type_vars_or_error(expr.hir_id, self.typeck_results.expr_ty_opt(expr)) + self.resolve_type_vars_or_error(expr.hir_id, self.typeck_results().expr_ty_opt(expr)) } pub(crate) fn expr_ty_adjusted(&self, expr: &hir::Expr<'_>) -> McResult> { - self.resolve_type_vars_or_error(expr.hir_id, self.typeck_results.expr_ty_adjusted_opt(expr)) + self.resolve_type_vars_or_error( + expr.hir_id, + self.typeck_results().expr_ty_adjusted_opt(expr), + ) } /// Returns the type of value that this pattern matches against. @@ -176,7 +176,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { // that these are never attached to binding patterns, so // actually this is somewhat "disjoint" from the code below // that aims to account for `ref x`. - if let Some(vec) = self.typeck_results.pat_adjustments().get(pat.hir_id) { + if let Some(vec) = self.typeck_results().pat_adjustments().get(pat.hir_id) { if let Some(first_ty) = vec.first() { debug!("pat_ty(pat={:?}) found adjusted ty `{:?}`", pat, first_ty); return Ok(*first_ty); @@ -197,7 +197,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { match pat.kind { PatKind::Binding(..) => { let bm = *self - .typeck_results + .typeck_results() .pat_binding_modes() .get(pat.hir_id) .expect("missing binding mode"); @@ -210,6 +210,9 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { Some(t) => Ok(t.ty), None => { debug!("By-ref binding of non-derefable type"); + self.tcx + .dcx() + .span_delayed_bug(pat.span, "by-ref binding of non-derefable type"); Err(()) } } @@ -237,7 +240,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { } } - helper(self, expr, self.typeck_results.expr_adjustments(expr)) + helper(self, expr, self.typeck_results().expr_adjustments(expr)) } pub(crate) fn cat_expr_adjusted( @@ -264,7 +267,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { adjustment::Adjust::Deref(overloaded) => { // Equivalent to *expr or something similar. let base = if let Some(deref) = overloaded { - let ref_ty = Ty::new_ref(self.tcx(), deref.region, target, deref.mutbl); + let ref_ty = Ty::new_ref(self.tcx, deref.region, target, deref.mutbl); self.cat_rvalue(expr.hir_id, ref_ty) } else { previous()? @@ -290,7 +293,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { let expr_ty = self.expr_ty(expr)?; match expr.kind { hir::ExprKind::Unary(hir::UnOp::Deref, e_base) => { - if self.typeck_results.is_method_call(expr) { + if self.typeck_results().is_method_call(expr) { self.cat_overloaded_place(expr, e_base) } else { let base = self.cat_expr(e_base)?; @@ -303,7 +306,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { debug!(?base); let field_idx = self - .typeck_results + .typeck_results() .field_indices() .get(expr.hir_id) .cloned() @@ -318,7 +321,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { } hir::ExprKind::Index(base, _, _) => { - if self.typeck_results.is_method_call(expr) { + if self.typeck_results().is_method_call(expr) { // If this is an index implemented by a method call, then it // will include an implicit deref of the result. // The call to index() returns a `&T` value, which @@ -332,7 +335,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { } hir::ExprKind::Path(ref qpath) => { - let res = self.typeck_results.qpath_res(qpath, expr.hir_id); + let res = self.typeck_results().qpath_res(qpath, expr.hir_id); self.cat_res(expr.hir_id, expr.span, expr_ty, res) } @@ -413,7 +416,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { /// about these dereferences, so we let it compute them as needed. #[instrument(level = "debug", skip(self), ret)] fn cat_upvar(&self, hir_id: HirId, var_id: HirId) -> McResult> { - let closure_expr_def_id = self.body_owner; + let closure_expr_def_id = self.inner_body_id; let upvar_id = ty::UpvarId { var_path: ty::UpvarPath { hir_id: var_id }, @@ -440,7 +443,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { let place_ty = base_place.place.ty(); let mut projections = base_place.place.projections; - let node_ty = self.typeck_results.node_type(node.hir_id()); + let node_ty = self.typeck_results().node_type(node.hir_id()); // Opaque types can't have field projections, but we can instead convert // the current place in-place (heh) to the hidden type, and then apply all // follow up projections on that. @@ -468,10 +471,12 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { let place_ty = self.expr_ty(expr)?; let base_ty = self.expr_ty_adjusted(base)?; - let ty::Ref(region, _, mutbl) = *base_ty.kind() else { + let ty::Ref(region, _, mutbl) = + *self.try_structurally_resolve_type(base.span, base_ty).kind() + else { span_bug!(expr.span, "cat_overloaded_place: base is not a reference"); }; - let ref_ty = Ty::new_ref(self.tcx(), region, place_ty, mutbl); + let ref_ty = Ty::new_ref(self.tcx, region, place_ty, mutbl); let base = self.cat_rvalue(expr.hir_id, ref_ty); self.cat_deref(expr, base) @@ -484,10 +489,17 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { base_place: PlaceWithHirId<'tcx>, ) -> McResult> { let base_curr_ty = base_place.place.ty(); - let deref_ty = match base_curr_ty.builtin_deref(true) { + let deref_ty = match self + .try_structurally_resolve_type(self.tcx.hir().span(node.hir_id()), base_curr_ty) + .builtin_deref(true) + { Some(mt) => mt.ty, None => { debug!("explicit deref of non-derefable type: {:?}", base_curr_ty); + self.tcx.dcx().span_delayed_bug( + self.tcx.hir().span(node.hir_id()), + "explicit deref of non-derefable type", + ); return Err(()); } }; @@ -522,10 +534,10 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { pat_hir_id: HirId, span: Span, ) -> McResult { - let res = self.typeck_results.qpath_res(qpath, pat_hir_id); - let ty = self.typeck_results.node_type(pat_hir_id); - let ty::Adt(adt_def, _) = ty.kind() else { - self.tcx() + let res = self.typeck_results().qpath_res(qpath, pat_hir_id); + let ty = self.typeck_results().node_type(pat_hir_id); + let ty::Adt(adt_def, _) = self.try_structurally_resolve_type(span, ty).kind() else { + self.tcx .dcx() .span_delayed_bug(span, "struct or tuple struct pattern not applied to an ADT"); return Err(()); @@ -556,11 +568,11 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { variant_index: VariantIdx, span: Span, ) -> McResult { - let ty = self.typeck_results.node_type(pat_hir_id); - match ty.kind() { + let ty = self.typeck_results().node_type(pat_hir_id); + match self.try_structurally_resolve_type(span, ty).kind() { ty::Adt(adt_def, _) => Ok(adt_def.variant(variant_index).fields.len()), _ => { - self.tcx() + self.tcx .dcx() .span_bug(span, "struct or tuple struct pattern not applied to an ADT"); } @@ -570,11 +582,11 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { /// Returns the total number of fields in a tuple used within a Tuple pattern. /// Here `pat_hir_id` is the HirId of the pattern itself. fn total_fields_in_tuple(&self, pat_hir_id: HirId, span: Span) -> McResult { - let ty = self.typeck_results.node_type(pat_hir_id); - match ty.kind() { + let ty = self.typeck_results().node_type(pat_hir_id); + match self.try_structurally_resolve_type(span, ty).kind() { ty::Tuple(args) => Ok(args.len()), _ => { - self.tcx().dcx().span_delayed_bug(span, "tuple pattern not applied to a tuple"); + self.tcx.dcx().span_delayed_bug(span, "tuple pattern not applied to a tuple"); Err(()) } } @@ -628,7 +640,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { // Then we see that to get the same result, we must start with // `deref { deref { place_foo }}` instead of `place_foo` since the pattern is now `Some(x,)` // and not `&&Some(x,)`, even though its assigned type is that of `&&Some(x,)`. - for _ in 0..self.typeck_results.pat_adjustments().get(pat.hir_id).map_or(0, |v| v.len()) { + for _ in 0..self.typeck_results().pat_adjustments().get(pat.hir_id).map_or(0, |v| v.len()) { debug!("applying adjustment to place_with_id={:?}", place_with_id); place_with_id = self.cat_deref(pat, place_with_id)?; } @@ -685,7 +697,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { for fp in field_pats { let field_ty = self.pat_ty_adjusted(fp.pat)?; let field_index = self - .typeck_results + .typeck_results() .field_indices() .get(fp.hir_id) .cloned() @@ -719,11 +731,11 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { self.cat_pattern_(subplace, subpat, op)?; } PatKind::Deref(subpat) => { - let mutable = self.typeck_results.pat_has_ref_mut_binding(subpat); + let mutable = self.typeck_results().pat_has_ref_mut_binding(subpat); let mutability = if mutable { hir::Mutability::Mut } else { hir::Mutability::Not }; - let re_erased = self.tcx().lifetimes.re_erased; + let re_erased = self.tcx.lifetimes.re_erased; let ty = self.pat_ty_adjusted(subpat)?; - let ty = Ty::new_ref(self.tcx(), re_erased, ty, mutability); + let ty = Ty::new_ref(self.tcx, re_erased, ty, mutability); // A deref pattern generates a temporary. let place = self.cat_rvalue(pat.hir_id, ty); self.cat_pattern_(place, subpat, op)?; @@ -732,6 +744,9 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { PatKind::Slice(before, ref slice, after) => { let Some(element_ty) = place_with_id.place.ty().builtin_index() else { debug!("explicit index of non-indexable type {:?}", place_with_id); + self.tcx + .dcx() + .span_delayed_bug(pat.span, "explicit index of non-indexable type"); return Err(()); }; let elt_place = self.cat_projection( diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index 2bf4f51a8038a..a90456e38c2b4 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -252,14 +252,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - euv::ExprUseVisitor::new( - &mut delegate, - &self.infcx, - closure_def_id, - self.param_env, - &self.typeck_results.borrow(), - ) - .consume_body(body); + euv::ExprUseVisitor::new(&mut delegate, self, closure_def_id).consume_body(body); // If a coroutine is comes from a coroutine-closure that is `move`, but // the coroutine-closure was inferred to be `FnOnce` during signature diff --git a/tests/ui/traits/next-solver/typeck/normalize-in-upvar-collection.rs b/tests/ui/traits/next-solver/typeck/normalize-in-upvar-collection.rs new file mode 100644 index 0000000000000..7e4e466fa4d63 --- /dev/null +++ b/tests/ui/traits/next-solver/typeck/normalize-in-upvar-collection.rs @@ -0,0 +1,15 @@ +//@ compile-flags: -Znext-solver +//@ check-pass + +struct Struct { + field: i32, +} + +fn hello(f: impl Fn() -> &'static Box<[i32]>, f2: impl Fn() -> &'static Struct) { + let cl = || { + let x = &f()[0]; + let y = &f2().field; + }; +} + +fn main() {}