From c7358b3fd0e6c857e91ecb4630bd3d0af55dab67 Mon Sep 17 00:00:00 2001 From: ouz-a Date: Sat, 13 Aug 2022 18:13:20 +0300 Subject: [PATCH 1/5] check discriminant types before span_mirbug --- compiler/rustc_borrowck/src/type_check/mod.rs | 19 +++++++++++-------- src/test/ui/typeck/issue-91633.rs | 8 ++++++++ 2 files changed, 19 insertions(+), 8 deletions(-) create mode 100644 src/test/ui/typeck/issue-91633.rs diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 7bf7f7357bf4f..cfb6685b9622b 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1270,14 +1270,17 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { if let Err(terr) = self.sub_types(rv_ty, place_ty, location.to_locations(), category) { - span_mirbug!( - self, - stmt, - "bad assignment ({:?} = {:?}): {:?}", - place_ty, - rv_ty, - terr - ); + // HACK(ouz-a): Bypasses ICE for #91633 + if rv_ty.discriminant_ty(self.tcx()) != place_ty.discriminant_ty(self.tcx()) { + span_mirbug!( + self, + stmt, + "bad assignment ({:?} = {:?}): {:?}", + place_ty, + rv_ty, + terr + ); + } } if let Some(annotation_index) = self.rvalue_user_ty(rv) { 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(){} From 8a34d82c3a74fc99cb773baa2cfcba3a4792a6d4 Mon Sep 17 00:00:00 2001 From: ouz-a Date: Sat, 13 Aug 2022 18:37:13 +0300 Subject: [PATCH 2/5] tidy --- compiler/rustc_borrowck/src/type_check/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index cfb6685b9622b..87e967e7d77eb 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1270,7 +1270,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { if let Err(terr) = self.sub_types(rv_ty, place_ty, location.to_locations(), category) { - // HACK(ouz-a): Bypasses ICE for #91633 + // HACK(ouz-a): Bypasses ICE for #91633 if rv_ty.discriminant_ty(self.tcx()) != place_ty.discriminant_ty(self.tcx()) { span_mirbug!( self, From c199140b15acc977877894bac62bc5f45352fb98 Mon Sep 17 00:00:00 2001 From: ouz-a Date: Sun, 14 Aug 2022 22:48:23 +0300 Subject: [PATCH 3/5] Check if lang item impl --- compiler/rustc_borrowck/src/type_check/mod.rs | 19 +++++------ compiler/rustc_typeck/src/check/writeback.rs | 33 ++++++++++++++++++- 2 files changed, 40 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 87e967e7d77eb..7bf7f7357bf4f 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1270,17 +1270,14 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { if let Err(terr) = self.sub_types(rv_ty, place_ty, location.to_locations(), category) { - // HACK(ouz-a): Bypasses ICE for #91633 - if rv_ty.discriminant_ty(self.tcx()) != place_ty.discriminant_ty(self.tcx()) { - span_mirbug!( - self, - stmt, - "bad assignment ({:?} = {:?}): {:?}", - place_ty, - rv_ty, - terr - ); - } + span_mirbug!( + self, + stmt, + "bad assignment ({:?} = {:?}): {:?}", + place_ty, + rv_ty, + terr + ); } if let Some(annotation_index) = self.rvalue_user_ty(rv) { diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs index f549807c39c91..f7cfd1f946133 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, SelectionContext}; use std::mem; use std::ops::ControlFlow; @@ -223,7 +226,35 @@ 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 { + let mut lang_index = false; + + // (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` if so we don't + // `fix_index_builtin_expr`. + 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([(*base_ty).into(), 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(), + self.fcx.param_env, + binder, + ); + let results = selection_context.select(&obligation); + + if results.is_ok() { + lang_index = true; + } + }); + + if base_ty.builtin_index().is_some() + && index_ty == self.fcx.tcx.types.usize + && !lang_index + { // Remove the method call record typeck_results.type_dependent_defs_mut().remove(e.hir_id); typeck_results.node_substs_mut().remove(e.hir_id); From 316ca56382eae0c3262fa9b8ee71ecb59d1a801b Mon Sep 17 00:00:00 2001 From: ouz-a Date: Sun, 14 Aug 2022 23:39:50 +0300 Subject: [PATCH 4/5] check tighter, resolve tys --- compiler/rustc_typeck/src/check/writeback.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs index f7cfd1f946133..69e320e12b23f 100644 --- a/compiler/rustc_typeck/src/check/writeback.rs +++ b/compiler/rustc_typeck/src/check/writeback.rs @@ -18,10 +18,10 @@ use rustc_middle::mir::FakeReadCause; use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCast}; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable}; -use rustc_middle::ty::{self, ClosureSizeProfileData, Ty, TyCtxt}; +use rustc_middle::ty::{self, ClosureSizeProfileData, Ty, TyCtxt, Uint}; use rustc_span::symbol::sym; use rustc_span::Span; -use rustc_trait_selection::traits::{self, SelectionContext}; +use rustc_trait_selection::traits::{self, ImplSource, SelectionContext}; use std::mem; use std::ops::ControlFlow; @@ -228,15 +228,17 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { let mut lang_index = false; + let resolved_base_ty = self.resolve(*base_ty, &base.span); + let resolved_index_ty = self.resolve(index_ty, &index.span); // (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` if so we don't + // here we check if the expr is `LangItem::Index` and index_ty is `usize` if so we don't // `fix_index_builtin_expr`. 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([(*base_ty).into(), index_ty.into()].iter()); + 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( @@ -246,9 +248,10 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { ); let results = selection_context.select(&obligation); - if results.is_ok() { + if let Ok(Some(ImplSource::Param(..))) = results && matches!(index_ty.kind(), Uint(ty::UintTy::Usize)){ lang_index = true; } + }); if base_ty.builtin_index().is_some() From 732975e3f0abb24cba0af2d5b2a7b388a42b718d Mon Sep 17 00:00:00 2001 From: ouz-a Date: Mon, 15 Aug 2022 00:38:04 +0300 Subject: [PATCH 5/5] create function for the check --- compiler/rustc_typeck/src/check/writeback.rs | 75 ++++++++++++-------- 1 file changed, 44 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs index 69e320e12b23f..c699d1b4816b0 100644 --- a/compiler/rustc_typeck/src/check/writeback.rs +++ b/compiler/rustc_typeck/src/check/writeback.rs @@ -18,7 +18,7 @@ use rustc_middle::mir::FakeReadCause; use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCast}; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable}; -use rustc_middle::ty::{self, ClosureSizeProfileData, Ty, TyCtxt, Uint}; +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}; @@ -195,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 @@ -226,37 +268,8 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { }); let index_ty = self.fcx.resolve_vars_if_possible(index_ty); - let mut lang_index = false; - - let resolved_base_ty = self.resolve(*base_ty, &base.span); - let resolved_index_ty = self.resolve(index_ty, &index.span); - // (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`. - 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(), - self.fcx.param_env, - binder, - ); - let results = selection_context.select(&obligation); - - if let Ok(Some(ImplSource::Param(..))) = results && matches!(index_ty.kind(), Uint(ty::UintTy::Usize)){ - lang_index = true; - } - - }); - - if base_ty.builtin_index().is_some() + if self.is_builtin_index(&e, *base_ty, index_ty, base.span, index.span) && index_ty == self.fcx.tcx.types.usize - && !lang_index { // Remove the method call record typeck_results.type_dependent_defs_mut().remove(e.hir_id);