diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs index f549807c39c91..c699d1b4816b0 100644 --- a/compiler/rustc_typeck/src/check/writeback.rs +++ b/compiler/rustc_typeck/src/check/writeback.rs @@ -9,8 +9,10 @@ use rustc_data_structures::fx::FxHashMap; use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; use rustc_hir::intravisit::{self, Visitor}; +use rustc_hir::lang_items::LangItem; use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282; use rustc_infer::infer::InferCtxt; +use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::hir::place::Place as HirPlace; use rustc_middle::mir::FakeReadCause; use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCast}; @@ -19,6 +21,7 @@ use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable}; use rustc_middle::ty::{self, ClosureSizeProfileData, Ty, TyCtxt}; use rustc_span::symbol::sym; use rustc_span::Span; +use rustc_trait_selection::traits::{self, ImplSource, SelectionContext}; use std::mem; use std::ops::ControlFlow; @@ -192,6 +195,48 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { } } + // (ouz-a #100498): Normally `[T] : std::ops::Index` should be normalized + // into [T] but currently `Where` clause stops the normalization process for it, + // here we check if the expr is `LangItem::Index` and index_ty is `usize` if so we don't + // `fix_index_builtin_expr`. + fn is_builtin_index( + &mut self, + e: &hir::Expr<'_>, + base: Ty<'tcx>, + index: Ty<'tcx>, + base_span: Span, + index_span: Span, + ) -> bool { + let mut ret = false; + if (&base).builtin_index().is_some() { + let resolved_base_ty = self.resolve(base, &base_span); + let resolved_index_ty = self.resolve(index, &index_span); + self.tcx().infer_ctxt().enter(|infcx| { + let mut selection_context = SelectionContext::new(&infcx); + + let def_id = self.tcx().require_lang_item(LangItem::Index, Some(e.span)); + let substs = self + .tcx() + .mk_substs([resolved_base_ty.into(), resolved_index_ty.into()].iter()); + let trait_ref = ty::TraitRef { def_id, substs }; + let binder = ty::Binder::dummy(trait_ref).without_const(); + let obligation = traits::Obligation::new( + traits::ObligationCause::dummy_with_span(e.span), + self.fcx.param_env, + binder, + ); + let results = selection_context.select(&obligation); + + if let Ok(Some(ImplSource::Param(..))) = results { + ret = false; + } else { + ret = true; + } + }); + } + ret + } + // Similar to operators, indexing is always assumed to be overloaded // Here, correct cases where an indexing expression can be simplified // to use builtin indexing because the index type is known to be @@ -223,7 +268,9 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { }); let index_ty = self.fcx.resolve_vars_if_possible(index_ty); - if base_ty.builtin_index().is_some() && index_ty == self.fcx.tcx.types.usize { + if self.is_builtin_index(&e, *base_ty, index_ty, base.span, index.span) + && index_ty == self.fcx.tcx.types.usize + { // Remove the method call record typeck_results.type_dependent_defs_mut().remove(e.hir_id); typeck_results.node_substs_mut().remove(e.hir_id); diff --git a/src/test/ui/typeck/issue-91633.rs b/src/test/ui/typeck/issue-91633.rs new file mode 100644 index 0000000000000..331a798dd7a36 --- /dev/null +++ b/src/test/ui/typeck/issue-91633.rs @@ -0,0 +1,8 @@ +// check-pass +fn f (it: &[T]) +where + [T] : std::ops::Index, +{ + let _ = &it[0]; +} +fn main(){}