From f28f77f2d9867247156b45d32db0f45448b5901f Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 22 Feb 2023 01:20:14 +0400 Subject: [PATCH 01/16] resolve: Remove `item_generics_num_lifetimes` --- compiler/rustc_metadata/src/rmeta/decoder.rs | 4 ---- compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs | 4 ---- compiler/rustc_resolve/src/lib.rs | 2 +- 3 files changed, 1 insertion(+), 9 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 0070e46ffdf02..54982e7fbab19 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -925,10 +925,6 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { tcx.mk_adt_def(did, adt_kind, variants, repr) } - fn get_generics(self, item_id: DefIndex, sess: &Session) -> ty::Generics { - self.root.tables.generics_of.get(self, item_id).unwrap().decode((self, sess)) - } - fn get_visibility(self, id: DefIndex) -> Visibility { self.root .tables diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index a98433953367b..089bd34ed32fb 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -565,10 +565,6 @@ impl CStore { self.get_crate_data(def.krate).def_kind(def.index) } - pub fn item_generics_num_lifetimes(&self, def_id: DefId, sess: &Session) -> usize { - self.get_crate_data(def_id.krate).get_generics(def_id.index, sess).own_counts().lifetimes - } - pub fn module_expansion_untracked(&self, def_id: DefId, sess: &Session) -> ExpnId { self.get_crate_data(def_id.krate).module_expansion(def_id.index, sess) } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index cd90fd3ef84d8..107c9a1991a52 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1168,7 +1168,7 @@ impl<'tcx> Resolver<'_, 'tcx> { if let Some(def_id) = def_id.as_local() { self.item_generics_num_lifetimes[&def_id] } else { - self.cstore().item_generics_num_lifetimes(def_id, self.tcx.sess) + self.tcx.generics_of(def_id).own_counts().lifetimes } } From d99e01fa7eb0dd2344040b3402a0f0961126d87e Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 22 Feb 2023 01:24:55 +0400 Subject: [PATCH 02/16] resolve: Remove `item_attrs_untracked` --- compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs | 8 -------- compiler/rustc_resolve/src/lib.rs | 5 +---- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 089bd34ed32fb..41b50a36718e9 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -576,14 +576,6 @@ impl CStore { self.get_crate_data(cnum).num_def_ids() } - pub fn item_attrs_untracked<'a>( - &'a self, - def_id: DefId, - sess: &'a Session, - ) -> impl Iterator + 'a { - self.get_crate_data(def_id.krate).get_item_attrs(def_id.index, sess) - } - pub fn get_proc_macro_quoted_span_untracked( &self, cnum: CrateNum, diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 107c9a1991a52..939f92d39f025 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1906,10 +1906,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { return v.clone(); } - let attr = self - .cstore() - .item_attrs_untracked(def_id, self.tcx.sess) - .find(|a| a.has_name(sym::rustc_legacy_const_generics))?; + let attr = self.tcx.get_attr(def_id, sym::rustc_legacy_const_generics)?; let mut ret = Vec::new(); for meta in attr.meta_item_list()? { match meta.lit()?.kind { From 52c73975b48b49ab6b14896a9d8d6fc665cf85da Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Tue, 14 Mar 2023 18:36:15 +0400 Subject: [PATCH 03/16] resolve: Use `item_name` and `opt_parent` in `Resolver::get_module` This is a cleanup that doesn't introduce new query calls, but this way `def_key` is decoded twice which may matter for performance or may not --- .../rustc_resolve/src/build_reduced_graph.rs | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 362ef693c48d5..a0613962a00e3 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -27,7 +27,6 @@ use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID}; use rustc_metadata::creader::LoadedMacro; use rustc_middle::metadata::ModChild; use rustc_middle::{bug, ty}; -use rustc_session::cstore::CrateStore; use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::Span; @@ -118,20 +117,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let def_kind = self.cstore().def_kind(def_id); match def_kind { DefKind::Mod | DefKind::Enum | DefKind::Trait => { - let def_key = self.cstore().def_key(def_id); - let parent = def_key.parent.map(|index| { - self.get_nearest_non_block_module(DefId { index, krate: def_id.krate }) - }); - let name = if let Some(cnum) = def_id.as_crate_root() { - self.cstore().crate_name(cnum) - } else { - def_key.disambiguated_data.data.get_opt_name().expect("module without name") - }; - + let parent = self + .tcx + .opt_parent(def_id) + .map(|parent_id| self.get_nearest_non_block_module(parent_id)); let expn_id = self.cstore().module_expansion_untracked(def_id, &self.tcx.sess); Some(self.new_module( parent, - ModuleKind::Def(def_kind, def_id, name), + ModuleKind::Def(def_kind, def_id, self.tcx.item_name(def_id)), expn_id, self.def_span(def_id), // FIXME: Account for `#[no_implicit_prelude]` attributes. From 18b59f5d6d6fab80b5526bf20859b5a906332e9a Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Tue, 14 Mar 2023 19:01:09 +0400 Subject: [PATCH 04/16] resolve: Minor cleanup to `Resolver::get_module` --- .../rustc_resolve/src/build_reduced_graph.rs | 35 +++++++++---------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index a0613962a00e3..fbac219c322fc 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -115,27 +115,24 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if !def_id.is_local() { let def_kind = self.cstore().def_kind(def_id); - match def_kind { - DefKind::Mod | DefKind::Enum | DefKind::Trait => { - let parent = self - .tcx - .opt_parent(def_id) - .map(|parent_id| self.get_nearest_non_block_module(parent_id)); - let expn_id = self.cstore().module_expansion_untracked(def_id, &self.tcx.sess); - Some(self.new_module( - parent, - ModuleKind::Def(def_kind, def_id, self.tcx.item_name(def_id)), - expn_id, - self.def_span(def_id), - // FIXME: Account for `#[no_implicit_prelude]` attributes. - parent.map_or(false, |module| module.no_implicit_prelude), - )) - } - _ => None, + if let DefKind::Mod | DefKind::Enum | DefKind::Trait = def_kind { + let parent = self + .tcx + .opt_parent(def_id) + .map(|parent_id| self.get_nearest_non_block_module(parent_id)); + let expn_id = self.cstore().module_expansion_untracked(def_id, &self.tcx.sess); + return Some(self.new_module( + parent, + ModuleKind::Def(def_kind, def_id, self.tcx.item_name(def_id)), + expn_id, + self.def_span(def_id), + // FIXME: Account for `#[no_implicit_prelude]` attributes. + parent.map_or(false, |module| module.no_implicit_prelude), + )); } - } else { - None } + + None } pub(crate) fn expn_def_scope(&mut self, expn_id: ExpnId) -> Module<'a> { From 009ed88789d5351c763cd6d1056fe2c1a040bf33 Mon Sep 17 00:00:00 2001 From: Evgenii Zheltonozhskii Date: Mon, 20 Mar 2023 16:38:38 +0200 Subject: [PATCH 05/16] Add `known-bug` test for typeid unsoundness issue --- .../typeid-equality-by-subtyping.rs | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 tests/ui/const-generics/generic_const_exprs/typeid-equality-by-subtyping.rs diff --git a/tests/ui/const-generics/generic_const_exprs/typeid-equality-by-subtyping.rs b/tests/ui/const-generics/generic_const_exprs/typeid-equality-by-subtyping.rs new file mode 100644 index 0000000000000..64317b9d39aae --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/typeid-equality-by-subtyping.rs @@ -0,0 +1,52 @@ +// check-pass +// known-bug: #97156 + +#![feature(const_type_id, generic_const_exprs)] +#![allow(incomplete_features)] + +use std::any::TypeId; +// `One` and `Two` are currently considered equal types, as both +// `One <: Two` and `One :> Two` holds. +type One = for<'a> fn(&'a (), &'a ()); +type Two = for<'a, 'b> fn(&'a (), &'b ()); +trait AssocCt { + const ASSOC: usize; +} +const fn to_usize() -> usize { + const WHAT_A_TYPE: TypeId = TypeId::of::(); + match TypeId::of::() { + WHAT_A_TYPE => 0, + _ => 1000, + } +} +impl AssocCt for T { + const ASSOC: usize = to_usize::(); +} + +trait WithAssoc { + type Assoc; +} +impl WithAssoc<()> for T where [(); ::ASSOC]: { + type Assoc = [u8; ::ASSOC]; +} + +fn generic(x: >::Assoc) -> >::Assoc +where + [(); ::ASSOC]:, + T: WithAssoc, +{ + x +} + + +fn unsound(x: >::Assoc) -> >::Assoc +where + One: WithAssoc, +{ + let x: >::Assoc = generic::(x); + x +} + +fn main() { + println!("{:?}", unsound::<()>([])); +} From 7c2ee33137cb3c42e6795804ef62d7eddc09e159 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 9 Mar 2023 21:53:18 +0000 Subject: [PATCH 06/16] Refine error spans for const args in hir typeck --- .../src/fn_ctxt/adjust_fulfillment_errors.rs | 46 +++++++++++-------- compiler/rustc_middle/src/ty/mod.rs | 15 ++++++ .../cross_crate_predicate.stderr | 8 ++-- tests/ui/const-generics/type_mismatch.stderr | 4 +- 4 files changed, 49 insertions(+), 24 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 ec14bd3c6f43e..e0ddb90c33b99 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 @@ -4,7 +4,7 @@ use rustc_hir::def::Res; use rustc_hir::def_id::DefId; use rustc_infer::traits::ObligationCauseCode; use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor}; -use rustc_span::{self, Span}; +use rustc_span::{self, symbol::kw, Span}; use rustc_trait_selection::traits; use std::ops::ControlFlow; @@ -25,17 +25,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { 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(), + ty::PredicateKind::Clause(ty::Clause::Trait(pred)) => pred.trait_ref.substs.to_vec(), + ty::PredicateKind::Clause(ty::Clause::Projection(pred)) => { + pred.projection_ty.substs.to_vec() + } + ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(arg, ty)) => { + vec![ty.into(), arg.into()] + } + ty::PredicateKind::ConstEvaluatable(e) => vec![e.into()], + _ => return false, }; - let find_param_matching = |matches: &dyn Fn(&ty::ParamTy) -> bool| { - predicate_substs.types().find_map(|ty| { - ty.walk().find_map(|arg| { + let find_param_matching = |matches: &dyn Fn(ty::ParamTerm) -> bool| { + predicate_substs.iter().find_map(|arg| { + arg.walk().find_map(|arg| { if let ty::GenericArgKind::Type(ty) = arg.unpack() - && let ty::Param(param_ty) = ty.kind() - && matches(param_ty) + && let ty::Param(param_ty) = *ty.kind() + && matches(ty::ParamTerm::Ty(param_ty)) + { + Some(arg) + } else if let ty::GenericArgKind::Const(ct) = arg.unpack() + && let ty::ConstKind::Param(param_ct) = ct.kind() + && matches(ty::ParamTerm::Const(param_ct)) { Some(arg) } else { @@ -47,21 +58,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // 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 + let mut param_to_point_at = find_param_matching(&|param_term| { + self.tcx.parent(generics.param_at(param_term.index(), 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 + let mut fallback_param_to_point_at = find_param_matching(&|param_term| { + self.tcx.parent(generics.param_at(param_term.index(), self.tcx).def_id) != def_id + && !matches!(param_term, ty::ParamTerm::Ty(ty) if ty.name == 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); + let mut self_param_to_point_at = find_param_matching( + &|param_term| matches!(param_term, ty::ParamTerm::Ty(ty) if ty.name == kw::SelfUpper), + ); // Finally, for ambiguity-related errors, we actually want to look // for a parameter that is the source of the inference type left @@ -225,14 +237,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .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() diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 298b2c3073cd3..bb11d8762ec67 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1035,6 +1035,21 @@ impl<'tcx> TermKind<'tcx> { } } +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub enum ParamTerm { + Ty(ParamTy), + Const(ParamConst), +} + +impl ParamTerm { + pub fn index(self) -> usize { + match self { + ParamTerm::Ty(ty) => ty.index as usize, + ParamTerm::Const(ct) => ct.index as usize, + } + } +} + /// This kind of predicate has no *direct* correspondent in the /// syntax, but it roughly corresponds to the syntactic forms: /// diff --git a/tests/ui/const-generics/generic_const_exprs/cross_crate_predicate.stderr b/tests/ui/const-generics/generic_const_exprs/cross_crate_predicate.stderr index 7b4d46b820976..6b3396a25cf97 100644 --- a/tests/ui/const-generics/generic_const_exprs/cross_crate_predicate.stderr +++ b/tests/ui/const-generics/generic_const_exprs/cross_crate_predicate.stderr @@ -1,8 +1,8 @@ error: unconstrained generic constant - --> $DIR/cross_crate_predicate.rs:7:13 + --> $DIR/cross_crate_predicate.rs:7:44 | LL | let _ = const_evaluatable_lib::test1::(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^ | = help: try adding a `where` bound using this expression: `where [(); std::mem::size_of::() - 1]:` note: required by a bound in `test1` @@ -12,10 +12,10 @@ LL | [u8; std::mem::size_of::() - 1]: Sized, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `test1` error: unconstrained generic constant - --> $DIR/cross_crate_predicate.rs:7:13 + --> $DIR/cross_crate_predicate.rs:7:44 | LL | let _ = const_evaluatable_lib::test1::(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^ | = help: try adding a `where` bound using this expression: `where [(); std::mem::size_of::() - 1]:` note: required by a bound in `test1` diff --git a/tests/ui/const-generics/type_mismatch.stderr b/tests/ui/const-generics/type_mismatch.stderr index 6d8955e411ec3..2831577b13269 100644 --- a/tests/ui/const-generics/type_mismatch.stderr +++ b/tests/ui/const-generics/type_mismatch.stderr @@ -1,8 +1,8 @@ error: the constant `N` is not of type `u8` - --> $DIR/type_mismatch.rs:2:5 + --> $DIR/type_mismatch.rs:2:11 | LL | bar::() - | ^^^^^^^^ + | ^ | note: required by a bound in `bar` --> $DIR/type_mismatch.rs:6:8 From 2e7472f6b29b6f24c0807fc164b308e916dcd70f Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 9 Mar 2023 22:08:48 +0000 Subject: [PATCH 07/16] Note type mismatch on ConstArgHasType --- .../src/traits/error_reporting/mod.rs | 14 ++++++++++++-- tests/ui/const-generics/type_mismatch.stderr | 2 +- tests/ui/transmutability/issue-101739-1.stderr | 2 +- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 41ffaeeac1c11..ebe9be640e09a 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1282,10 +1282,20 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ), ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => { - self.tcx.sess.struct_span_err( + let mut diag = self.tcx.sess.struct_span_err( span, &format!("the constant `{}` is not of type `{}`", ct, ty), - ) + ); + self.note_type_err( + &mut diag, + &obligation.cause, + None, + None, + TypeError::Sorts(ty::error::ExpectedFound::new(true, ty, ct.ty())), + false, + false, + ); + diag } } } diff --git a/tests/ui/const-generics/type_mismatch.stderr b/tests/ui/const-generics/type_mismatch.stderr index 2831577b13269..394dd44d40d33 100644 --- a/tests/ui/const-generics/type_mismatch.stderr +++ b/tests/ui/const-generics/type_mismatch.stderr @@ -2,7 +2,7 @@ error: the constant `N` is not of type `u8` --> $DIR/type_mismatch.rs:2:11 | LL | bar::() - | ^ + | ^ expected `u8`, found `usize` | note: required by a bound in `bar` --> $DIR/type_mismatch.rs:6:8 diff --git a/tests/ui/transmutability/issue-101739-1.stderr b/tests/ui/transmutability/issue-101739-1.stderr index f0fa93722b89b..bf947d0ea4a6c 100644 --- a/tests/ui/transmutability/issue-101739-1.stderr +++ b/tests/ui/transmutability/issue-101739-1.stderr @@ -8,7 +8,7 @@ error: the constant `ASSUME_ALIGNMENT` is not of type `Assume` --> $DIR/issue-101739-1.rs:8:14 | LL | Dst: BikeshedIntrinsicFrom, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Assume`, found `bool` | note: required by a bound in `BikeshedIntrinsicFrom` --> $SRC_DIR/core/src/mem/transmutability.rs:LL:COL From ec25f087488a1913982fc6b28b66574ee4791d14 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Wed, 22 Mar 2023 01:11:25 -0700 Subject: [PATCH 08/16] Demonstration test for MIR building of checked shift operators --- tests/mir-opt/building/shifts.rs | 20 +++ .../shifts.shift_signed.built.after.mir | 147 ++++++++++++++++++ .../shifts.shift_unsigned.built.after.mir | 147 ++++++++++++++++++ 3 files changed, 314 insertions(+) create mode 100644 tests/mir-opt/building/shifts.rs create mode 100644 tests/mir-opt/building/shifts.shift_signed.built.after.mir create mode 100644 tests/mir-opt/building/shifts.shift_unsigned.built.after.mir diff --git a/tests/mir-opt/building/shifts.rs b/tests/mir-opt/building/shifts.rs new file mode 100644 index 0000000000000..4b63a00a304dc --- /dev/null +++ b/tests/mir-opt/building/shifts.rs @@ -0,0 +1,20 @@ +// compile-flags: -C debug-assertions=yes + +// EMIT_MIR shifts.shift_signed.built.after.mir +fn shift_signed(small: i8, big: u128, a: i8, b: i32, c: i128) -> ([i8; 3], [u128; 3]) { + ( + [small >> a, small >> b, small >> c], + [big << a, big << b, big << c], + ) +} + +// EMIT_MIR shifts.shift_unsigned.built.after.mir +fn shift_unsigned(small: u8, big: i128, a: u8, b: u32, c: u128) -> ([u8; 3], [i128; 3]) { + ( + [small >> a, small >> b, small >> c], + [big << a, big << b, big << c], + ) +} + +fn main() { +} diff --git a/tests/mir-opt/building/shifts.shift_signed.built.after.mir b/tests/mir-opt/building/shifts.shift_signed.built.after.mir new file mode 100644 index 0000000000000..10fcff0283740 --- /dev/null +++ b/tests/mir-opt/building/shifts.shift_signed.built.after.mir @@ -0,0 +1,147 @@ +// MIR for `shift_signed` after built + +fn shift_signed(_1: i8, _2: u128, _3: i8, _4: i32, _5: i128) -> ([i8; 3], [u128; 3]) { + debug small => _1; // in scope 0 at $DIR/shifts.rs:+0:17: +0:22 + debug big => _2; // in scope 0 at $DIR/shifts.rs:+0:28: +0:31 + debug a => _3; // in scope 0 at $DIR/shifts.rs:+0:39: +0:40 + debug b => _4; // in scope 0 at $DIR/shifts.rs:+0:46: +0:47 + debug c => _5; // in scope 0 at $DIR/shifts.rs:+0:54: +0:55 + let mut _0: ([i8; 3], [u128; 3]); // return place in scope 0 at $DIR/shifts.rs:+0:66: +0:86 + let mut _6: [i8; 3]; // in scope 0 at $DIR/shifts.rs:+2:9: +2:45 + let mut _7: i8; // in scope 0 at $DIR/shifts.rs:+2:10: +2:20 + let mut _8: i8; // in scope 0 at $DIR/shifts.rs:+2:10: +2:15 + let mut _9: i8; // in scope 0 at $DIR/shifts.rs:+2:19: +2:20 + let mut _10: i8; // in scope 0 at $DIR/shifts.rs:+2:10: +2:20 + let mut _11: bool; // in scope 0 at $DIR/shifts.rs:+2:10: +2:20 + let mut _12: i8; // in scope 0 at $DIR/shifts.rs:+2:22: +2:32 + let mut _13: i8; // in scope 0 at $DIR/shifts.rs:+2:22: +2:27 + let mut _14: i32; // in scope 0 at $DIR/shifts.rs:+2:31: +2:32 + let mut _15: i32; // in scope 0 at $DIR/shifts.rs:+2:22: +2:32 + let mut _16: bool; // in scope 0 at $DIR/shifts.rs:+2:22: +2:32 + let mut _17: i8; // in scope 0 at $DIR/shifts.rs:+2:34: +2:44 + let mut _18: i8; // in scope 0 at $DIR/shifts.rs:+2:34: +2:39 + let mut _19: i128; // in scope 0 at $DIR/shifts.rs:+2:43: +2:44 + let mut _20: i128; // in scope 0 at $DIR/shifts.rs:+2:34: +2:44 + let mut _21: bool; // in scope 0 at $DIR/shifts.rs:+2:34: +2:44 + let mut _22: [u128; 3]; // in scope 0 at $DIR/shifts.rs:+3:9: +3:39 + let mut _23: u128; // in scope 0 at $DIR/shifts.rs:+3:10: +3:18 + let mut _24: u128; // in scope 0 at $DIR/shifts.rs:+3:10: +3:13 + let mut _25: i8; // in scope 0 at $DIR/shifts.rs:+3:17: +3:18 + let mut _26: i8; // in scope 0 at $DIR/shifts.rs:+3:10: +3:18 + let mut _27: bool; // in scope 0 at $DIR/shifts.rs:+3:10: +3:18 + let mut _28: u128; // in scope 0 at $DIR/shifts.rs:+3:20: +3:28 + let mut _29: u128; // in scope 0 at $DIR/shifts.rs:+3:20: +3:23 + let mut _30: i32; // in scope 0 at $DIR/shifts.rs:+3:27: +3:28 + let mut _31: i32; // in scope 0 at $DIR/shifts.rs:+3:20: +3:28 + let mut _32: bool; // in scope 0 at $DIR/shifts.rs:+3:20: +3:28 + let mut _33: u128; // in scope 0 at $DIR/shifts.rs:+3:30: +3:38 + let mut _34: u128; // in scope 0 at $DIR/shifts.rs:+3:30: +3:33 + let mut _35: i128; // in scope 0 at $DIR/shifts.rs:+3:37: +3:38 + let mut _36: i128; // in scope 0 at $DIR/shifts.rs:+3:30: +3:38 + let mut _37: bool; // in scope 0 at $DIR/shifts.rs:+3:30: +3:38 + + bb0: { + StorageLive(_6); // scope 0 at $DIR/shifts.rs:+2:9: +2:45 + StorageLive(_7); // scope 0 at $DIR/shifts.rs:+2:10: +2:20 + StorageLive(_8); // scope 0 at $DIR/shifts.rs:+2:10: +2:15 + _8 = _1; // scope 0 at $DIR/shifts.rs:+2:10: +2:15 + StorageLive(_9); // scope 0 at $DIR/shifts.rs:+2:19: +2:20 + _9 = _3; // scope 0 at $DIR/shifts.rs:+2:19: +2:20 + _10 = BitAnd(_9, const -8_i8); // scope 0 at $DIR/shifts.rs:+2:10: +2:20 + _11 = Ne(move _10, const 0_i8); // scope 0 at $DIR/shifts.rs:+2:10: +2:20 + assert(!move _11, "attempt to shift right by `{}`, which would overflow", _9) -> [success: bb1, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+2:10: +2:20 + } + + bb1: { + _7 = Shr(move _8, move _9); // scope 0 at $DIR/shifts.rs:+2:10: +2:20 + StorageDead(_9); // scope 0 at $DIR/shifts.rs:+2:19: +2:20 + StorageDead(_8); // scope 0 at $DIR/shifts.rs:+2:19: +2:20 + StorageLive(_12); // scope 0 at $DIR/shifts.rs:+2:22: +2:32 + StorageLive(_13); // scope 0 at $DIR/shifts.rs:+2:22: +2:27 + _13 = _1; // scope 0 at $DIR/shifts.rs:+2:22: +2:27 + StorageLive(_14); // scope 0 at $DIR/shifts.rs:+2:31: +2:32 + _14 = _4; // scope 0 at $DIR/shifts.rs:+2:31: +2:32 + _15 = BitAnd(_14, const -8_i32); // scope 0 at $DIR/shifts.rs:+2:22: +2:32 + _16 = Ne(move _15, const 0_i32); // scope 0 at $DIR/shifts.rs:+2:22: +2:32 + assert(!move _16, "attempt to shift right by `{}`, which would overflow", _14) -> [success: bb2, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+2:22: +2:32 + } + + bb2: { + _12 = Shr(move _13, move _14); // scope 0 at $DIR/shifts.rs:+2:22: +2:32 + StorageDead(_14); // scope 0 at $DIR/shifts.rs:+2:31: +2:32 + StorageDead(_13); // scope 0 at $DIR/shifts.rs:+2:31: +2:32 + StorageLive(_17); // scope 0 at $DIR/shifts.rs:+2:34: +2:44 + StorageLive(_18); // scope 0 at $DIR/shifts.rs:+2:34: +2:39 + _18 = _1; // scope 0 at $DIR/shifts.rs:+2:34: +2:39 + StorageLive(_19); // scope 0 at $DIR/shifts.rs:+2:43: +2:44 + _19 = _5; // scope 0 at $DIR/shifts.rs:+2:43: +2:44 + _20 = BitAnd(_19, const -8_i128); // scope 0 at $DIR/shifts.rs:+2:34: +2:44 + _21 = Ne(move _20, const 0_i128); // scope 0 at $DIR/shifts.rs:+2:34: +2:44 + assert(!move _21, "attempt to shift right by `{}`, which would overflow", _19) -> [success: bb3, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+2:34: +2:44 + } + + bb3: { + _17 = Shr(move _18, move _19); // scope 0 at $DIR/shifts.rs:+2:34: +2:44 + StorageDead(_19); // scope 0 at $DIR/shifts.rs:+2:43: +2:44 + StorageDead(_18); // scope 0 at $DIR/shifts.rs:+2:43: +2:44 + _6 = [move _7, move _12, move _17]; // scope 0 at $DIR/shifts.rs:+2:9: +2:45 + StorageDead(_17); // scope 0 at $DIR/shifts.rs:+2:44: +2:45 + StorageDead(_12); // scope 0 at $DIR/shifts.rs:+2:44: +2:45 + StorageDead(_7); // scope 0 at $DIR/shifts.rs:+2:44: +2:45 + StorageLive(_22); // scope 0 at $DIR/shifts.rs:+3:9: +3:39 + StorageLive(_23); // scope 0 at $DIR/shifts.rs:+3:10: +3:18 + StorageLive(_24); // scope 0 at $DIR/shifts.rs:+3:10: +3:13 + _24 = _2; // scope 0 at $DIR/shifts.rs:+3:10: +3:13 + StorageLive(_25); // scope 0 at $DIR/shifts.rs:+3:17: +3:18 + _25 = _3; // scope 0 at $DIR/shifts.rs:+3:17: +3:18 + _26 = BitAnd(_25, const i8::MIN); // scope 0 at $DIR/shifts.rs:+3:10: +3:18 + _27 = Ne(move _26, const 0_i8); // scope 0 at $DIR/shifts.rs:+3:10: +3:18 + assert(!move _27, "attempt to shift left by `{}`, which would overflow", _25) -> [success: bb4, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+3:10: +3:18 + } + + bb4: { + _23 = Shl(move _24, move _25); // scope 0 at $DIR/shifts.rs:+3:10: +3:18 + StorageDead(_25); // scope 0 at $DIR/shifts.rs:+3:17: +3:18 + StorageDead(_24); // scope 0 at $DIR/shifts.rs:+3:17: +3:18 + StorageLive(_28); // scope 0 at $DIR/shifts.rs:+3:20: +3:28 + StorageLive(_29); // scope 0 at $DIR/shifts.rs:+3:20: +3:23 + _29 = _2; // scope 0 at $DIR/shifts.rs:+3:20: +3:23 + StorageLive(_30); // scope 0 at $DIR/shifts.rs:+3:27: +3:28 + _30 = _4; // scope 0 at $DIR/shifts.rs:+3:27: +3:28 + _31 = BitAnd(_30, const -128_i32); // scope 0 at $DIR/shifts.rs:+3:20: +3:28 + _32 = Ne(move _31, const 0_i32); // scope 0 at $DIR/shifts.rs:+3:20: +3:28 + assert(!move _32, "attempt to shift left by `{}`, which would overflow", _30) -> [success: bb5, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+3:20: +3:28 + } + + bb5: { + _28 = Shl(move _29, move _30); // scope 0 at $DIR/shifts.rs:+3:20: +3:28 + StorageDead(_30); // scope 0 at $DIR/shifts.rs:+3:27: +3:28 + StorageDead(_29); // scope 0 at $DIR/shifts.rs:+3:27: +3:28 + StorageLive(_33); // scope 0 at $DIR/shifts.rs:+3:30: +3:38 + StorageLive(_34); // scope 0 at $DIR/shifts.rs:+3:30: +3:33 + _34 = _2; // scope 0 at $DIR/shifts.rs:+3:30: +3:33 + StorageLive(_35); // scope 0 at $DIR/shifts.rs:+3:37: +3:38 + _35 = _5; // scope 0 at $DIR/shifts.rs:+3:37: +3:38 + _36 = BitAnd(_35, const -128_i128); // scope 0 at $DIR/shifts.rs:+3:30: +3:38 + _37 = Ne(move _36, const 0_i128); // scope 0 at $DIR/shifts.rs:+3:30: +3:38 + assert(!move _37, "attempt to shift left by `{}`, which would overflow", _35) -> [success: bb6, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+3:30: +3:38 + } + + bb6: { + _33 = Shl(move _34, move _35); // scope 0 at $DIR/shifts.rs:+3:30: +3:38 + StorageDead(_35); // scope 0 at $DIR/shifts.rs:+3:37: +3:38 + StorageDead(_34); // scope 0 at $DIR/shifts.rs:+3:37: +3:38 + _22 = [move _23, move _28, move _33]; // scope 0 at $DIR/shifts.rs:+3:9: +3:39 + StorageDead(_33); // scope 0 at $DIR/shifts.rs:+3:38: +3:39 + StorageDead(_28); // scope 0 at $DIR/shifts.rs:+3:38: +3:39 + StorageDead(_23); // scope 0 at $DIR/shifts.rs:+3:38: +3:39 + _0 = (move _6, move _22); // scope 0 at $DIR/shifts.rs:+1:5: +4:6 + StorageDead(_22); // scope 0 at $DIR/shifts.rs:+4:5: +4:6 + StorageDead(_6); // scope 0 at $DIR/shifts.rs:+4:5: +4:6 + return; // scope 0 at $DIR/shifts.rs:+5:2: +5:2 + } + + bb7 (cleanup): { + resume; // scope 0 at $DIR/shifts.rs:+0:1: +5:2 + } +} diff --git a/tests/mir-opt/building/shifts.shift_unsigned.built.after.mir b/tests/mir-opt/building/shifts.shift_unsigned.built.after.mir new file mode 100644 index 0000000000000..89b9cb24cfd1b --- /dev/null +++ b/tests/mir-opt/building/shifts.shift_unsigned.built.after.mir @@ -0,0 +1,147 @@ +// MIR for `shift_unsigned` after built + +fn shift_unsigned(_1: u8, _2: i128, _3: u8, _4: u32, _5: u128) -> ([u8; 3], [i128; 3]) { + debug small => _1; // in scope 0 at $DIR/shifts.rs:+0:19: +0:24 + debug big => _2; // in scope 0 at $DIR/shifts.rs:+0:30: +0:33 + debug a => _3; // in scope 0 at $DIR/shifts.rs:+0:41: +0:42 + debug b => _4; // in scope 0 at $DIR/shifts.rs:+0:48: +0:49 + debug c => _5; // in scope 0 at $DIR/shifts.rs:+0:56: +0:57 + let mut _0: ([u8; 3], [i128; 3]); // return place in scope 0 at $DIR/shifts.rs:+0:68: +0:88 + let mut _6: [u8; 3]; // in scope 0 at $DIR/shifts.rs:+2:9: +2:45 + let mut _7: u8; // in scope 0 at $DIR/shifts.rs:+2:10: +2:20 + let mut _8: u8; // in scope 0 at $DIR/shifts.rs:+2:10: +2:15 + let mut _9: u8; // in scope 0 at $DIR/shifts.rs:+2:19: +2:20 + let mut _10: u8; // in scope 0 at $DIR/shifts.rs:+2:10: +2:20 + let mut _11: bool; // in scope 0 at $DIR/shifts.rs:+2:10: +2:20 + let mut _12: u8; // in scope 0 at $DIR/shifts.rs:+2:22: +2:32 + let mut _13: u8; // in scope 0 at $DIR/shifts.rs:+2:22: +2:27 + let mut _14: u32; // in scope 0 at $DIR/shifts.rs:+2:31: +2:32 + let mut _15: u32; // in scope 0 at $DIR/shifts.rs:+2:22: +2:32 + let mut _16: bool; // in scope 0 at $DIR/shifts.rs:+2:22: +2:32 + let mut _17: u8; // in scope 0 at $DIR/shifts.rs:+2:34: +2:44 + let mut _18: u8; // in scope 0 at $DIR/shifts.rs:+2:34: +2:39 + let mut _19: u128; // in scope 0 at $DIR/shifts.rs:+2:43: +2:44 + let mut _20: u128; // in scope 0 at $DIR/shifts.rs:+2:34: +2:44 + let mut _21: bool; // in scope 0 at $DIR/shifts.rs:+2:34: +2:44 + let mut _22: [i128; 3]; // in scope 0 at $DIR/shifts.rs:+3:9: +3:39 + let mut _23: i128; // in scope 0 at $DIR/shifts.rs:+3:10: +3:18 + let mut _24: i128; // in scope 0 at $DIR/shifts.rs:+3:10: +3:13 + let mut _25: u8; // in scope 0 at $DIR/shifts.rs:+3:17: +3:18 + let mut _26: u8; // in scope 0 at $DIR/shifts.rs:+3:10: +3:18 + let mut _27: bool; // in scope 0 at $DIR/shifts.rs:+3:10: +3:18 + let mut _28: i128; // in scope 0 at $DIR/shifts.rs:+3:20: +3:28 + let mut _29: i128; // in scope 0 at $DIR/shifts.rs:+3:20: +3:23 + let mut _30: u32; // in scope 0 at $DIR/shifts.rs:+3:27: +3:28 + let mut _31: u32; // in scope 0 at $DIR/shifts.rs:+3:20: +3:28 + let mut _32: bool; // in scope 0 at $DIR/shifts.rs:+3:20: +3:28 + let mut _33: i128; // in scope 0 at $DIR/shifts.rs:+3:30: +3:38 + let mut _34: i128; // in scope 0 at $DIR/shifts.rs:+3:30: +3:33 + let mut _35: u128; // in scope 0 at $DIR/shifts.rs:+3:37: +3:38 + let mut _36: u128; // in scope 0 at $DIR/shifts.rs:+3:30: +3:38 + let mut _37: bool; // in scope 0 at $DIR/shifts.rs:+3:30: +3:38 + + bb0: { + StorageLive(_6); // scope 0 at $DIR/shifts.rs:+2:9: +2:45 + StorageLive(_7); // scope 0 at $DIR/shifts.rs:+2:10: +2:20 + StorageLive(_8); // scope 0 at $DIR/shifts.rs:+2:10: +2:15 + _8 = _1; // scope 0 at $DIR/shifts.rs:+2:10: +2:15 + StorageLive(_9); // scope 0 at $DIR/shifts.rs:+2:19: +2:20 + _9 = _3; // scope 0 at $DIR/shifts.rs:+2:19: +2:20 + _10 = BitAnd(_9, const 248_u8); // scope 0 at $DIR/shifts.rs:+2:10: +2:20 + _11 = Ne(move _10, const 0_u8); // scope 0 at $DIR/shifts.rs:+2:10: +2:20 + assert(!move _11, "attempt to shift right by `{}`, which would overflow", _9) -> [success: bb1, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+2:10: +2:20 + } + + bb1: { + _7 = Shr(move _8, move _9); // scope 0 at $DIR/shifts.rs:+2:10: +2:20 + StorageDead(_9); // scope 0 at $DIR/shifts.rs:+2:19: +2:20 + StorageDead(_8); // scope 0 at $DIR/shifts.rs:+2:19: +2:20 + StorageLive(_12); // scope 0 at $DIR/shifts.rs:+2:22: +2:32 + StorageLive(_13); // scope 0 at $DIR/shifts.rs:+2:22: +2:27 + _13 = _1; // scope 0 at $DIR/shifts.rs:+2:22: +2:27 + StorageLive(_14); // scope 0 at $DIR/shifts.rs:+2:31: +2:32 + _14 = _4; // scope 0 at $DIR/shifts.rs:+2:31: +2:32 + _15 = BitAnd(_14, const 4294967288_u32); // scope 0 at $DIR/shifts.rs:+2:22: +2:32 + _16 = Ne(move _15, const 0_u32); // scope 0 at $DIR/shifts.rs:+2:22: +2:32 + assert(!move _16, "attempt to shift right by `{}`, which would overflow", _14) -> [success: bb2, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+2:22: +2:32 + } + + bb2: { + _12 = Shr(move _13, move _14); // scope 0 at $DIR/shifts.rs:+2:22: +2:32 + StorageDead(_14); // scope 0 at $DIR/shifts.rs:+2:31: +2:32 + StorageDead(_13); // scope 0 at $DIR/shifts.rs:+2:31: +2:32 + StorageLive(_17); // scope 0 at $DIR/shifts.rs:+2:34: +2:44 + StorageLive(_18); // scope 0 at $DIR/shifts.rs:+2:34: +2:39 + _18 = _1; // scope 0 at $DIR/shifts.rs:+2:34: +2:39 + StorageLive(_19); // scope 0 at $DIR/shifts.rs:+2:43: +2:44 + _19 = _5; // scope 0 at $DIR/shifts.rs:+2:43: +2:44 + _20 = BitAnd(_19, const 340282366920938463463374607431768211448_u128); // scope 0 at $DIR/shifts.rs:+2:34: +2:44 + _21 = Ne(move _20, const 0_u128); // scope 0 at $DIR/shifts.rs:+2:34: +2:44 + assert(!move _21, "attempt to shift right by `{}`, which would overflow", _19) -> [success: bb3, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+2:34: +2:44 + } + + bb3: { + _17 = Shr(move _18, move _19); // scope 0 at $DIR/shifts.rs:+2:34: +2:44 + StorageDead(_19); // scope 0 at $DIR/shifts.rs:+2:43: +2:44 + StorageDead(_18); // scope 0 at $DIR/shifts.rs:+2:43: +2:44 + _6 = [move _7, move _12, move _17]; // scope 0 at $DIR/shifts.rs:+2:9: +2:45 + StorageDead(_17); // scope 0 at $DIR/shifts.rs:+2:44: +2:45 + StorageDead(_12); // scope 0 at $DIR/shifts.rs:+2:44: +2:45 + StorageDead(_7); // scope 0 at $DIR/shifts.rs:+2:44: +2:45 + StorageLive(_22); // scope 0 at $DIR/shifts.rs:+3:9: +3:39 + StorageLive(_23); // scope 0 at $DIR/shifts.rs:+3:10: +3:18 + StorageLive(_24); // scope 0 at $DIR/shifts.rs:+3:10: +3:13 + _24 = _2; // scope 0 at $DIR/shifts.rs:+3:10: +3:13 + StorageLive(_25); // scope 0 at $DIR/shifts.rs:+3:17: +3:18 + _25 = _3; // scope 0 at $DIR/shifts.rs:+3:17: +3:18 + _26 = BitAnd(_25, const 128_u8); // scope 0 at $DIR/shifts.rs:+3:10: +3:18 + _27 = Ne(move _26, const 0_u8); // scope 0 at $DIR/shifts.rs:+3:10: +3:18 + assert(!move _27, "attempt to shift left by `{}`, which would overflow", _25) -> [success: bb4, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+3:10: +3:18 + } + + bb4: { + _23 = Shl(move _24, move _25); // scope 0 at $DIR/shifts.rs:+3:10: +3:18 + StorageDead(_25); // scope 0 at $DIR/shifts.rs:+3:17: +3:18 + StorageDead(_24); // scope 0 at $DIR/shifts.rs:+3:17: +3:18 + StorageLive(_28); // scope 0 at $DIR/shifts.rs:+3:20: +3:28 + StorageLive(_29); // scope 0 at $DIR/shifts.rs:+3:20: +3:23 + _29 = _2; // scope 0 at $DIR/shifts.rs:+3:20: +3:23 + StorageLive(_30); // scope 0 at $DIR/shifts.rs:+3:27: +3:28 + _30 = _4; // scope 0 at $DIR/shifts.rs:+3:27: +3:28 + _31 = BitAnd(_30, const 4294967168_u32); // scope 0 at $DIR/shifts.rs:+3:20: +3:28 + _32 = Ne(move _31, const 0_u32); // scope 0 at $DIR/shifts.rs:+3:20: +3:28 + assert(!move _32, "attempt to shift left by `{}`, which would overflow", _30) -> [success: bb5, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+3:20: +3:28 + } + + bb5: { + _28 = Shl(move _29, move _30); // scope 0 at $DIR/shifts.rs:+3:20: +3:28 + StorageDead(_30); // scope 0 at $DIR/shifts.rs:+3:27: +3:28 + StorageDead(_29); // scope 0 at $DIR/shifts.rs:+3:27: +3:28 + StorageLive(_33); // scope 0 at $DIR/shifts.rs:+3:30: +3:38 + StorageLive(_34); // scope 0 at $DIR/shifts.rs:+3:30: +3:33 + _34 = _2; // scope 0 at $DIR/shifts.rs:+3:30: +3:33 + StorageLive(_35); // scope 0 at $DIR/shifts.rs:+3:37: +3:38 + _35 = _5; // scope 0 at $DIR/shifts.rs:+3:37: +3:38 + _36 = BitAnd(_35, const 340282366920938463463374607431768211328_u128); // scope 0 at $DIR/shifts.rs:+3:30: +3:38 + _37 = Ne(move _36, const 0_u128); // scope 0 at $DIR/shifts.rs:+3:30: +3:38 + assert(!move _37, "attempt to shift left by `{}`, which would overflow", _35) -> [success: bb6, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+3:30: +3:38 + } + + bb6: { + _33 = Shl(move _34, move _35); // scope 0 at $DIR/shifts.rs:+3:30: +3:38 + StorageDead(_35); // scope 0 at $DIR/shifts.rs:+3:37: +3:38 + StorageDead(_34); // scope 0 at $DIR/shifts.rs:+3:37: +3:38 + _22 = [move _23, move _28, move _33]; // scope 0 at $DIR/shifts.rs:+3:9: +3:39 + StorageDead(_33); // scope 0 at $DIR/shifts.rs:+3:38: +3:39 + StorageDead(_28); // scope 0 at $DIR/shifts.rs:+3:38: +3:39 + StorageDead(_23); // scope 0 at $DIR/shifts.rs:+3:38: +3:39 + _0 = (move _6, move _22); // scope 0 at $DIR/shifts.rs:+1:5: +4:6 + StorageDead(_22); // scope 0 at $DIR/shifts.rs:+4:5: +4:6 + StorageDead(_6); // scope 0 at $DIR/shifts.rs:+4:5: +4:6 + return; // scope 0 at $DIR/shifts.rs:+5:2: +5:2 + } + + bb7 (cleanup): { + resume; // scope 0 at $DIR/shifts.rs:+0:1: +5:2 + } +} From b537e6bc53bfee64d1e8f8f8d28b2418bddc5a91 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Wed, 22 Mar 2023 01:06:19 -0700 Subject: [PATCH 09/16] Generate simpler MIR for shifts --- .../src/build/expr/as_rvalue.rs | 56 +++--- compiler/rustc_type_ir/src/lib.rs | 22 +++ .../shifts.shift_signed.built.after.mir | 48 ++--- .../shifts.shift_unsigned.built.after.mir | 176 ++++++++---------- .../mir-opt/issue_101973.inner.ConstProp.diff | 28 +-- 5 files changed, 175 insertions(+), 155 deletions(-) diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs index 140d1154718f7..3b775f590a4c1 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs @@ -566,41 +566,51 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Rvalue::Use(Operand::Move(val)) } BinOp::Shl | BinOp::Shr if self.check_overflow && ty.is_integral() => { - // Consider that the shift overflows if `rhs < 0` or `rhs >= bits`. - // This can be encoded as a single operation as `(rhs & -bits) != 0`. - let (size, _) = ty.int_size_and_signed(self.tcx); - let bits = size.bits(); - debug_assert!(bits.is_power_of_two()); - let mask = !((bits - 1) as u128); - + // For an unsigned RHS, the shift is in-range for `rhs < bits`. + // For a signed RHS, `IntToInt` cast to the equivalent unsigned + // type and do that same comparison. Because the type is the + // same size, there's no negative shift amount that ends up + // overlapping with valid ones, thus it catches negatives too. + let (lhs_size, _) = ty.int_size_and_signed(self.tcx); let rhs_ty = rhs.ty(&self.local_decls, self.tcx); let (rhs_size, _) = rhs_ty.int_size_and_signed(self.tcx); - let mask = Operand::const_from_scalar( + + let (unsigned_rhs, unsigned_ty) = match rhs_ty.kind() { + ty::Uint(_) => (rhs.to_copy(), rhs_ty), + ty::Int(int_width) => { + let uint_ty = self.tcx.mk_mach_uint(int_width.to_unsigned()); + let rhs_temp = self.temp(uint_ty, span); + self.cfg.push_assign( + block, + source_info, + rhs_temp, + Rvalue::Cast(CastKind::IntToInt, rhs.to_copy(), uint_ty), + ); + (Operand::Move(rhs_temp), uint_ty) + } + _ => unreachable!("only integers are shiftable"), + }; + + // This can't overflow because the largest shiftable types are 128-bit, + // which fits in `u8`, the smallest possible `unsigned_ty`. + // (And `from_uint` will `bug!` if that's ever no longer true.) + let lhs_bits = Operand::const_from_scalar( self.tcx, - rhs_ty, - Scalar::from_uint(rhs_size.truncate(mask), rhs_size), + unsigned_ty, + Scalar::from_uint(lhs_size.bits(), rhs_size), span, ); - let outer_bits = self.temp(rhs_ty, span); - self.cfg.push_assign( - block, - source_info, - outer_bits, - Rvalue::BinaryOp(BinOp::BitAnd, Box::new((rhs.to_copy(), mask))), - ); - - let overflows = self.temp(bool_ty, span); - let zero = self.zero_literal(span, rhs_ty); + let inbounds = self.temp(bool_ty, span); self.cfg.push_assign( block, source_info, - overflows, - Rvalue::BinaryOp(BinOp::Ne, Box::new((Operand::Move(outer_bits), zero))), + inbounds, + Rvalue::BinaryOp(BinOp::Lt, Box::new((unsigned_rhs, lhs_bits))), ); let overflow_err = AssertKind::Overflow(op, lhs.to_copy(), rhs.to_copy()); - block = self.assert(block, Operand::Move(overflows), false, overflow_err, span); + block = self.assert(block, Operand::Move(inbounds), true, overflow_err, span); Rvalue::BinaryOp(op, Box::new((lhs, rhs))) } BinOp::Div | BinOp::Rem if ty.is_integral() => { diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index 5a991e03dee52..8b23fbc75833c 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -432,6 +432,17 @@ impl IntTy { _ => *self, } } + + pub fn to_unsigned(self) -> UintTy { + match self { + IntTy::Isize => UintTy::Usize, + IntTy::I8 => UintTy::U8, + IntTy::I16 => UintTy::U16, + IntTy::I32 => UintTy::U32, + IntTy::I64 => UintTy::U64, + IntTy::I128 => UintTy::U128, + } + } } #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, Debug)] @@ -479,6 +490,17 @@ impl UintTy { _ => *self, } } + + pub fn to_signed(self) -> IntTy { + match self { + UintTy::Usize => IntTy::Isize, + UintTy::U8 => IntTy::I8, + UintTy::U16 => IntTy::I16, + UintTy::U32 => IntTy::I32, + UintTy::U64 => IntTy::I64, + UintTy::U128 => IntTy::I128, + } + } } #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] diff --git a/tests/mir-opt/building/shifts.shift_signed.built.after.mir b/tests/mir-opt/building/shifts.shift_signed.built.after.mir index 10fcff0283740..028777cefdd10 100644 --- a/tests/mir-opt/building/shifts.shift_signed.built.after.mir +++ b/tests/mir-opt/building/shifts.shift_signed.built.after.mir @@ -11,33 +11,33 @@ fn shift_signed(_1: i8, _2: u128, _3: i8, _4: i32, _5: i128) -> ([i8; 3], [u128; let mut _7: i8; // in scope 0 at $DIR/shifts.rs:+2:10: +2:20 let mut _8: i8; // in scope 0 at $DIR/shifts.rs:+2:10: +2:15 let mut _9: i8; // in scope 0 at $DIR/shifts.rs:+2:19: +2:20 - let mut _10: i8; // in scope 0 at $DIR/shifts.rs:+2:10: +2:20 + let mut _10: u8; // in scope 0 at $DIR/shifts.rs:+2:10: +2:20 let mut _11: bool; // in scope 0 at $DIR/shifts.rs:+2:10: +2:20 let mut _12: i8; // in scope 0 at $DIR/shifts.rs:+2:22: +2:32 let mut _13: i8; // in scope 0 at $DIR/shifts.rs:+2:22: +2:27 let mut _14: i32; // in scope 0 at $DIR/shifts.rs:+2:31: +2:32 - let mut _15: i32; // in scope 0 at $DIR/shifts.rs:+2:22: +2:32 + let mut _15: u32; // in scope 0 at $DIR/shifts.rs:+2:22: +2:32 let mut _16: bool; // in scope 0 at $DIR/shifts.rs:+2:22: +2:32 let mut _17: i8; // in scope 0 at $DIR/shifts.rs:+2:34: +2:44 let mut _18: i8; // in scope 0 at $DIR/shifts.rs:+2:34: +2:39 let mut _19: i128; // in scope 0 at $DIR/shifts.rs:+2:43: +2:44 - let mut _20: i128; // in scope 0 at $DIR/shifts.rs:+2:34: +2:44 + let mut _20: u128; // in scope 0 at $DIR/shifts.rs:+2:34: +2:44 let mut _21: bool; // in scope 0 at $DIR/shifts.rs:+2:34: +2:44 let mut _22: [u128; 3]; // in scope 0 at $DIR/shifts.rs:+3:9: +3:39 let mut _23: u128; // in scope 0 at $DIR/shifts.rs:+3:10: +3:18 let mut _24: u128; // in scope 0 at $DIR/shifts.rs:+3:10: +3:13 let mut _25: i8; // in scope 0 at $DIR/shifts.rs:+3:17: +3:18 - let mut _26: i8; // in scope 0 at $DIR/shifts.rs:+3:10: +3:18 + let mut _26: u8; // in scope 0 at $DIR/shifts.rs:+3:10: +3:18 let mut _27: bool; // in scope 0 at $DIR/shifts.rs:+3:10: +3:18 let mut _28: u128; // in scope 0 at $DIR/shifts.rs:+3:20: +3:28 let mut _29: u128; // in scope 0 at $DIR/shifts.rs:+3:20: +3:23 let mut _30: i32; // in scope 0 at $DIR/shifts.rs:+3:27: +3:28 - let mut _31: i32; // in scope 0 at $DIR/shifts.rs:+3:20: +3:28 + let mut _31: u32; // in scope 0 at $DIR/shifts.rs:+3:20: +3:28 let mut _32: bool; // in scope 0 at $DIR/shifts.rs:+3:20: +3:28 let mut _33: u128; // in scope 0 at $DIR/shifts.rs:+3:30: +3:38 let mut _34: u128; // in scope 0 at $DIR/shifts.rs:+3:30: +3:33 let mut _35: i128; // in scope 0 at $DIR/shifts.rs:+3:37: +3:38 - let mut _36: i128; // in scope 0 at $DIR/shifts.rs:+3:30: +3:38 + let mut _36: u128; // in scope 0 at $DIR/shifts.rs:+3:30: +3:38 let mut _37: bool; // in scope 0 at $DIR/shifts.rs:+3:30: +3:38 bb0: { @@ -47,9 +47,9 @@ fn shift_signed(_1: i8, _2: u128, _3: i8, _4: i32, _5: i128) -> ([i8; 3], [u128; _8 = _1; // scope 0 at $DIR/shifts.rs:+2:10: +2:15 StorageLive(_9); // scope 0 at $DIR/shifts.rs:+2:19: +2:20 _9 = _3; // scope 0 at $DIR/shifts.rs:+2:19: +2:20 - _10 = BitAnd(_9, const -8_i8); // scope 0 at $DIR/shifts.rs:+2:10: +2:20 - _11 = Ne(move _10, const 0_i8); // scope 0 at $DIR/shifts.rs:+2:10: +2:20 - assert(!move _11, "attempt to shift right by `{}`, which would overflow", _9) -> [success: bb1, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+2:10: +2:20 + _10 = _9 as u8 (IntToInt); // scope 0 at $DIR/shifts.rs:+2:10: +2:20 + _11 = Lt(move _10, const 8_u8); // scope 0 at $DIR/shifts.rs:+2:10: +2:20 + assert(move _11, "attempt to shift right by `{}`, which would overflow", _9) -> [success: bb1, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+2:10: +2:20 } bb1: { @@ -61,9 +61,9 @@ fn shift_signed(_1: i8, _2: u128, _3: i8, _4: i32, _5: i128) -> ([i8; 3], [u128; _13 = _1; // scope 0 at $DIR/shifts.rs:+2:22: +2:27 StorageLive(_14); // scope 0 at $DIR/shifts.rs:+2:31: +2:32 _14 = _4; // scope 0 at $DIR/shifts.rs:+2:31: +2:32 - _15 = BitAnd(_14, const -8_i32); // scope 0 at $DIR/shifts.rs:+2:22: +2:32 - _16 = Ne(move _15, const 0_i32); // scope 0 at $DIR/shifts.rs:+2:22: +2:32 - assert(!move _16, "attempt to shift right by `{}`, which would overflow", _14) -> [success: bb2, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+2:22: +2:32 + _15 = _14 as u32 (IntToInt); // scope 0 at $DIR/shifts.rs:+2:22: +2:32 + _16 = Lt(move _15, const 8_u32); // scope 0 at $DIR/shifts.rs:+2:22: +2:32 + assert(move _16, "attempt to shift right by `{}`, which would overflow", _14) -> [success: bb2, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+2:22: +2:32 } bb2: { @@ -75,9 +75,9 @@ fn shift_signed(_1: i8, _2: u128, _3: i8, _4: i32, _5: i128) -> ([i8; 3], [u128; _18 = _1; // scope 0 at $DIR/shifts.rs:+2:34: +2:39 StorageLive(_19); // scope 0 at $DIR/shifts.rs:+2:43: +2:44 _19 = _5; // scope 0 at $DIR/shifts.rs:+2:43: +2:44 - _20 = BitAnd(_19, const -8_i128); // scope 0 at $DIR/shifts.rs:+2:34: +2:44 - _21 = Ne(move _20, const 0_i128); // scope 0 at $DIR/shifts.rs:+2:34: +2:44 - assert(!move _21, "attempt to shift right by `{}`, which would overflow", _19) -> [success: bb3, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+2:34: +2:44 + _20 = _19 as u128 (IntToInt); // scope 0 at $DIR/shifts.rs:+2:34: +2:44 + _21 = Lt(move _20, const 8_u128); // scope 0 at $DIR/shifts.rs:+2:34: +2:44 + assert(move _21, "attempt to shift right by `{}`, which would overflow", _19) -> [success: bb3, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+2:34: +2:44 } bb3: { @@ -94,9 +94,9 @@ fn shift_signed(_1: i8, _2: u128, _3: i8, _4: i32, _5: i128) -> ([i8; 3], [u128; _24 = _2; // scope 0 at $DIR/shifts.rs:+3:10: +3:13 StorageLive(_25); // scope 0 at $DIR/shifts.rs:+3:17: +3:18 _25 = _3; // scope 0 at $DIR/shifts.rs:+3:17: +3:18 - _26 = BitAnd(_25, const i8::MIN); // scope 0 at $DIR/shifts.rs:+3:10: +3:18 - _27 = Ne(move _26, const 0_i8); // scope 0 at $DIR/shifts.rs:+3:10: +3:18 - assert(!move _27, "attempt to shift left by `{}`, which would overflow", _25) -> [success: bb4, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+3:10: +3:18 + _26 = _25 as u8 (IntToInt); // scope 0 at $DIR/shifts.rs:+3:10: +3:18 + _27 = Lt(move _26, const 128_u8); // scope 0 at $DIR/shifts.rs:+3:10: +3:18 + assert(move _27, "attempt to shift left by `{}`, which would overflow", _25) -> [success: bb4, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+3:10: +3:18 } bb4: { @@ -108,9 +108,9 @@ fn shift_signed(_1: i8, _2: u128, _3: i8, _4: i32, _5: i128) -> ([i8; 3], [u128; _29 = _2; // scope 0 at $DIR/shifts.rs:+3:20: +3:23 StorageLive(_30); // scope 0 at $DIR/shifts.rs:+3:27: +3:28 _30 = _4; // scope 0 at $DIR/shifts.rs:+3:27: +3:28 - _31 = BitAnd(_30, const -128_i32); // scope 0 at $DIR/shifts.rs:+3:20: +3:28 - _32 = Ne(move _31, const 0_i32); // scope 0 at $DIR/shifts.rs:+3:20: +3:28 - assert(!move _32, "attempt to shift left by `{}`, which would overflow", _30) -> [success: bb5, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+3:20: +3:28 + _31 = _30 as u32 (IntToInt); // scope 0 at $DIR/shifts.rs:+3:20: +3:28 + _32 = Lt(move _31, const 128_u32); // scope 0 at $DIR/shifts.rs:+3:20: +3:28 + assert(move _32, "attempt to shift left by `{}`, which would overflow", _30) -> [success: bb5, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+3:20: +3:28 } bb5: { @@ -122,9 +122,9 @@ fn shift_signed(_1: i8, _2: u128, _3: i8, _4: i32, _5: i128) -> ([i8; 3], [u128; _34 = _2; // scope 0 at $DIR/shifts.rs:+3:30: +3:33 StorageLive(_35); // scope 0 at $DIR/shifts.rs:+3:37: +3:38 _35 = _5; // scope 0 at $DIR/shifts.rs:+3:37: +3:38 - _36 = BitAnd(_35, const -128_i128); // scope 0 at $DIR/shifts.rs:+3:30: +3:38 - _37 = Ne(move _36, const 0_i128); // scope 0 at $DIR/shifts.rs:+3:30: +3:38 - assert(!move _37, "attempt to shift left by `{}`, which would overflow", _35) -> [success: bb6, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+3:30: +3:38 + _36 = _35 as u128 (IntToInt); // scope 0 at $DIR/shifts.rs:+3:30: +3:38 + _37 = Lt(move _36, const 128_u128); // scope 0 at $DIR/shifts.rs:+3:30: +3:38 + assert(move _37, "attempt to shift left by `{}`, which would overflow", _35) -> [success: bb6, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+3:30: +3:38 } bb6: { diff --git a/tests/mir-opt/building/shifts.shift_unsigned.built.after.mir b/tests/mir-opt/building/shifts.shift_unsigned.built.after.mir index 89b9cb24cfd1b..04da2d20d242f 100644 --- a/tests/mir-opt/building/shifts.shift_unsigned.built.after.mir +++ b/tests/mir-opt/building/shifts.shift_unsigned.built.after.mir @@ -11,34 +11,28 @@ fn shift_unsigned(_1: u8, _2: i128, _3: u8, _4: u32, _5: u128) -> ([u8; 3], [i12 let mut _7: u8; // in scope 0 at $DIR/shifts.rs:+2:10: +2:20 let mut _8: u8; // in scope 0 at $DIR/shifts.rs:+2:10: +2:15 let mut _9: u8; // in scope 0 at $DIR/shifts.rs:+2:19: +2:20 - let mut _10: u8; // in scope 0 at $DIR/shifts.rs:+2:10: +2:20 - let mut _11: bool; // in scope 0 at $DIR/shifts.rs:+2:10: +2:20 - let mut _12: u8; // in scope 0 at $DIR/shifts.rs:+2:22: +2:32 - let mut _13: u8; // in scope 0 at $DIR/shifts.rs:+2:22: +2:27 - let mut _14: u32; // in scope 0 at $DIR/shifts.rs:+2:31: +2:32 - let mut _15: u32; // in scope 0 at $DIR/shifts.rs:+2:22: +2:32 - let mut _16: bool; // in scope 0 at $DIR/shifts.rs:+2:22: +2:32 - let mut _17: u8; // in scope 0 at $DIR/shifts.rs:+2:34: +2:44 - let mut _18: u8; // in scope 0 at $DIR/shifts.rs:+2:34: +2:39 - let mut _19: u128; // in scope 0 at $DIR/shifts.rs:+2:43: +2:44 - let mut _20: u128; // in scope 0 at $DIR/shifts.rs:+2:34: +2:44 - let mut _21: bool; // in scope 0 at $DIR/shifts.rs:+2:34: +2:44 - let mut _22: [i128; 3]; // in scope 0 at $DIR/shifts.rs:+3:9: +3:39 - let mut _23: i128; // in scope 0 at $DIR/shifts.rs:+3:10: +3:18 - let mut _24: i128; // in scope 0 at $DIR/shifts.rs:+3:10: +3:13 - let mut _25: u8; // in scope 0 at $DIR/shifts.rs:+3:17: +3:18 - let mut _26: u8; // in scope 0 at $DIR/shifts.rs:+3:10: +3:18 - let mut _27: bool; // in scope 0 at $DIR/shifts.rs:+3:10: +3:18 - let mut _28: i128; // in scope 0 at $DIR/shifts.rs:+3:20: +3:28 - let mut _29: i128; // in scope 0 at $DIR/shifts.rs:+3:20: +3:23 - let mut _30: u32; // in scope 0 at $DIR/shifts.rs:+3:27: +3:28 - let mut _31: u32; // in scope 0 at $DIR/shifts.rs:+3:20: +3:28 - let mut _32: bool; // in scope 0 at $DIR/shifts.rs:+3:20: +3:28 - let mut _33: i128; // in scope 0 at $DIR/shifts.rs:+3:30: +3:38 - let mut _34: i128; // in scope 0 at $DIR/shifts.rs:+3:30: +3:33 - let mut _35: u128; // in scope 0 at $DIR/shifts.rs:+3:37: +3:38 - let mut _36: u128; // in scope 0 at $DIR/shifts.rs:+3:30: +3:38 - let mut _37: bool; // in scope 0 at $DIR/shifts.rs:+3:30: +3:38 + let mut _10: bool; // in scope 0 at $DIR/shifts.rs:+2:10: +2:20 + let mut _11: u8; // in scope 0 at $DIR/shifts.rs:+2:22: +2:32 + let mut _12: u8; // in scope 0 at $DIR/shifts.rs:+2:22: +2:27 + let mut _13: u32; // in scope 0 at $DIR/shifts.rs:+2:31: +2:32 + let mut _14: bool; // in scope 0 at $DIR/shifts.rs:+2:22: +2:32 + let mut _15: u8; // in scope 0 at $DIR/shifts.rs:+2:34: +2:44 + let mut _16: u8; // in scope 0 at $DIR/shifts.rs:+2:34: +2:39 + let mut _17: u128; // in scope 0 at $DIR/shifts.rs:+2:43: +2:44 + let mut _18: bool; // in scope 0 at $DIR/shifts.rs:+2:34: +2:44 + let mut _19: [i128; 3]; // in scope 0 at $DIR/shifts.rs:+3:9: +3:39 + let mut _20: i128; // in scope 0 at $DIR/shifts.rs:+3:10: +3:18 + let mut _21: i128; // in scope 0 at $DIR/shifts.rs:+3:10: +3:13 + let mut _22: u8; // in scope 0 at $DIR/shifts.rs:+3:17: +3:18 + let mut _23: bool; // in scope 0 at $DIR/shifts.rs:+3:10: +3:18 + let mut _24: i128; // in scope 0 at $DIR/shifts.rs:+3:20: +3:28 + let mut _25: i128; // in scope 0 at $DIR/shifts.rs:+3:20: +3:23 + let mut _26: u32; // in scope 0 at $DIR/shifts.rs:+3:27: +3:28 + let mut _27: bool; // in scope 0 at $DIR/shifts.rs:+3:20: +3:28 + let mut _28: i128; // in scope 0 at $DIR/shifts.rs:+3:30: +3:38 + let mut _29: i128; // in scope 0 at $DIR/shifts.rs:+3:30: +3:33 + let mut _30: u128; // in scope 0 at $DIR/shifts.rs:+3:37: +3:38 + let mut _31: bool; // in scope 0 at $DIR/shifts.rs:+3:30: +3:38 bb0: { StorageLive(_6); // scope 0 at $DIR/shifts.rs:+2:9: +2:45 @@ -47,96 +41,90 @@ fn shift_unsigned(_1: u8, _2: i128, _3: u8, _4: u32, _5: u128) -> ([u8; 3], [i12 _8 = _1; // scope 0 at $DIR/shifts.rs:+2:10: +2:15 StorageLive(_9); // scope 0 at $DIR/shifts.rs:+2:19: +2:20 _9 = _3; // scope 0 at $DIR/shifts.rs:+2:19: +2:20 - _10 = BitAnd(_9, const 248_u8); // scope 0 at $DIR/shifts.rs:+2:10: +2:20 - _11 = Ne(move _10, const 0_u8); // scope 0 at $DIR/shifts.rs:+2:10: +2:20 - assert(!move _11, "attempt to shift right by `{}`, which would overflow", _9) -> [success: bb1, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+2:10: +2:20 + _10 = Lt(_9, const 8_u8); // scope 0 at $DIR/shifts.rs:+2:10: +2:20 + assert(move _10, "attempt to shift right by `{}`, which would overflow", _9) -> [success: bb1, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+2:10: +2:20 } bb1: { _7 = Shr(move _8, move _9); // scope 0 at $DIR/shifts.rs:+2:10: +2:20 StorageDead(_9); // scope 0 at $DIR/shifts.rs:+2:19: +2:20 StorageDead(_8); // scope 0 at $DIR/shifts.rs:+2:19: +2:20 - StorageLive(_12); // scope 0 at $DIR/shifts.rs:+2:22: +2:32 - StorageLive(_13); // scope 0 at $DIR/shifts.rs:+2:22: +2:27 - _13 = _1; // scope 0 at $DIR/shifts.rs:+2:22: +2:27 - StorageLive(_14); // scope 0 at $DIR/shifts.rs:+2:31: +2:32 - _14 = _4; // scope 0 at $DIR/shifts.rs:+2:31: +2:32 - _15 = BitAnd(_14, const 4294967288_u32); // scope 0 at $DIR/shifts.rs:+2:22: +2:32 - _16 = Ne(move _15, const 0_u32); // scope 0 at $DIR/shifts.rs:+2:22: +2:32 - assert(!move _16, "attempt to shift right by `{}`, which would overflow", _14) -> [success: bb2, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+2:22: +2:32 + StorageLive(_11); // scope 0 at $DIR/shifts.rs:+2:22: +2:32 + StorageLive(_12); // scope 0 at $DIR/shifts.rs:+2:22: +2:27 + _12 = _1; // scope 0 at $DIR/shifts.rs:+2:22: +2:27 + StorageLive(_13); // scope 0 at $DIR/shifts.rs:+2:31: +2:32 + _13 = _4; // scope 0 at $DIR/shifts.rs:+2:31: +2:32 + _14 = Lt(_13, const 8_u32); // scope 0 at $DIR/shifts.rs:+2:22: +2:32 + assert(move _14, "attempt to shift right by `{}`, which would overflow", _13) -> [success: bb2, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+2:22: +2:32 } bb2: { - _12 = Shr(move _13, move _14); // scope 0 at $DIR/shifts.rs:+2:22: +2:32 - StorageDead(_14); // scope 0 at $DIR/shifts.rs:+2:31: +2:32 + _11 = Shr(move _12, move _13); // scope 0 at $DIR/shifts.rs:+2:22: +2:32 StorageDead(_13); // scope 0 at $DIR/shifts.rs:+2:31: +2:32 - StorageLive(_17); // scope 0 at $DIR/shifts.rs:+2:34: +2:44 - StorageLive(_18); // scope 0 at $DIR/shifts.rs:+2:34: +2:39 - _18 = _1; // scope 0 at $DIR/shifts.rs:+2:34: +2:39 - StorageLive(_19); // scope 0 at $DIR/shifts.rs:+2:43: +2:44 - _19 = _5; // scope 0 at $DIR/shifts.rs:+2:43: +2:44 - _20 = BitAnd(_19, const 340282366920938463463374607431768211448_u128); // scope 0 at $DIR/shifts.rs:+2:34: +2:44 - _21 = Ne(move _20, const 0_u128); // scope 0 at $DIR/shifts.rs:+2:34: +2:44 - assert(!move _21, "attempt to shift right by `{}`, which would overflow", _19) -> [success: bb3, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+2:34: +2:44 + StorageDead(_12); // scope 0 at $DIR/shifts.rs:+2:31: +2:32 + StorageLive(_15); // scope 0 at $DIR/shifts.rs:+2:34: +2:44 + StorageLive(_16); // scope 0 at $DIR/shifts.rs:+2:34: +2:39 + _16 = _1; // scope 0 at $DIR/shifts.rs:+2:34: +2:39 + StorageLive(_17); // scope 0 at $DIR/shifts.rs:+2:43: +2:44 + _17 = _5; // scope 0 at $DIR/shifts.rs:+2:43: +2:44 + _18 = Lt(_17, const 8_u128); // scope 0 at $DIR/shifts.rs:+2:34: +2:44 + assert(move _18, "attempt to shift right by `{}`, which would overflow", _17) -> [success: bb3, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+2:34: +2:44 } bb3: { - _17 = Shr(move _18, move _19); // scope 0 at $DIR/shifts.rs:+2:34: +2:44 - StorageDead(_19); // scope 0 at $DIR/shifts.rs:+2:43: +2:44 - StorageDead(_18); // scope 0 at $DIR/shifts.rs:+2:43: +2:44 - _6 = [move _7, move _12, move _17]; // scope 0 at $DIR/shifts.rs:+2:9: +2:45 - StorageDead(_17); // scope 0 at $DIR/shifts.rs:+2:44: +2:45 - StorageDead(_12); // scope 0 at $DIR/shifts.rs:+2:44: +2:45 + _15 = Shr(move _16, move _17); // scope 0 at $DIR/shifts.rs:+2:34: +2:44 + StorageDead(_17); // scope 0 at $DIR/shifts.rs:+2:43: +2:44 + StorageDead(_16); // scope 0 at $DIR/shifts.rs:+2:43: +2:44 + _6 = [move _7, move _11, move _15]; // scope 0 at $DIR/shifts.rs:+2:9: +2:45 + StorageDead(_15); // scope 0 at $DIR/shifts.rs:+2:44: +2:45 + StorageDead(_11); // scope 0 at $DIR/shifts.rs:+2:44: +2:45 StorageDead(_7); // scope 0 at $DIR/shifts.rs:+2:44: +2:45 - StorageLive(_22); // scope 0 at $DIR/shifts.rs:+3:9: +3:39 - StorageLive(_23); // scope 0 at $DIR/shifts.rs:+3:10: +3:18 - StorageLive(_24); // scope 0 at $DIR/shifts.rs:+3:10: +3:13 - _24 = _2; // scope 0 at $DIR/shifts.rs:+3:10: +3:13 - StorageLive(_25); // scope 0 at $DIR/shifts.rs:+3:17: +3:18 - _25 = _3; // scope 0 at $DIR/shifts.rs:+3:17: +3:18 - _26 = BitAnd(_25, const 128_u8); // scope 0 at $DIR/shifts.rs:+3:10: +3:18 - _27 = Ne(move _26, const 0_u8); // scope 0 at $DIR/shifts.rs:+3:10: +3:18 - assert(!move _27, "attempt to shift left by `{}`, which would overflow", _25) -> [success: bb4, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+3:10: +3:18 + StorageLive(_19); // scope 0 at $DIR/shifts.rs:+3:9: +3:39 + StorageLive(_20); // scope 0 at $DIR/shifts.rs:+3:10: +3:18 + StorageLive(_21); // scope 0 at $DIR/shifts.rs:+3:10: +3:13 + _21 = _2; // scope 0 at $DIR/shifts.rs:+3:10: +3:13 + StorageLive(_22); // scope 0 at $DIR/shifts.rs:+3:17: +3:18 + _22 = _3; // scope 0 at $DIR/shifts.rs:+3:17: +3:18 + _23 = Lt(_22, const 128_u8); // scope 0 at $DIR/shifts.rs:+3:10: +3:18 + assert(move _23, "attempt to shift left by `{}`, which would overflow", _22) -> [success: bb4, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+3:10: +3:18 } bb4: { - _23 = Shl(move _24, move _25); // scope 0 at $DIR/shifts.rs:+3:10: +3:18 - StorageDead(_25); // scope 0 at $DIR/shifts.rs:+3:17: +3:18 - StorageDead(_24); // scope 0 at $DIR/shifts.rs:+3:17: +3:18 - StorageLive(_28); // scope 0 at $DIR/shifts.rs:+3:20: +3:28 - StorageLive(_29); // scope 0 at $DIR/shifts.rs:+3:20: +3:23 - _29 = _2; // scope 0 at $DIR/shifts.rs:+3:20: +3:23 - StorageLive(_30); // scope 0 at $DIR/shifts.rs:+3:27: +3:28 - _30 = _4; // scope 0 at $DIR/shifts.rs:+3:27: +3:28 - _31 = BitAnd(_30, const 4294967168_u32); // scope 0 at $DIR/shifts.rs:+3:20: +3:28 - _32 = Ne(move _31, const 0_u32); // scope 0 at $DIR/shifts.rs:+3:20: +3:28 - assert(!move _32, "attempt to shift left by `{}`, which would overflow", _30) -> [success: bb5, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+3:20: +3:28 + _20 = Shl(move _21, move _22); // scope 0 at $DIR/shifts.rs:+3:10: +3:18 + StorageDead(_22); // scope 0 at $DIR/shifts.rs:+3:17: +3:18 + StorageDead(_21); // scope 0 at $DIR/shifts.rs:+3:17: +3:18 + StorageLive(_24); // scope 0 at $DIR/shifts.rs:+3:20: +3:28 + StorageLive(_25); // scope 0 at $DIR/shifts.rs:+3:20: +3:23 + _25 = _2; // scope 0 at $DIR/shifts.rs:+3:20: +3:23 + StorageLive(_26); // scope 0 at $DIR/shifts.rs:+3:27: +3:28 + _26 = _4; // scope 0 at $DIR/shifts.rs:+3:27: +3:28 + _27 = Lt(_26, const 128_u32); // scope 0 at $DIR/shifts.rs:+3:20: +3:28 + assert(move _27, "attempt to shift left by `{}`, which would overflow", _26) -> [success: bb5, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+3:20: +3:28 } bb5: { - _28 = Shl(move _29, move _30); // scope 0 at $DIR/shifts.rs:+3:20: +3:28 - StorageDead(_30); // scope 0 at $DIR/shifts.rs:+3:27: +3:28 - StorageDead(_29); // scope 0 at $DIR/shifts.rs:+3:27: +3:28 - StorageLive(_33); // scope 0 at $DIR/shifts.rs:+3:30: +3:38 - StorageLive(_34); // scope 0 at $DIR/shifts.rs:+3:30: +3:33 - _34 = _2; // scope 0 at $DIR/shifts.rs:+3:30: +3:33 - StorageLive(_35); // scope 0 at $DIR/shifts.rs:+3:37: +3:38 - _35 = _5; // scope 0 at $DIR/shifts.rs:+3:37: +3:38 - _36 = BitAnd(_35, const 340282366920938463463374607431768211328_u128); // scope 0 at $DIR/shifts.rs:+3:30: +3:38 - _37 = Ne(move _36, const 0_u128); // scope 0 at $DIR/shifts.rs:+3:30: +3:38 - assert(!move _37, "attempt to shift left by `{}`, which would overflow", _35) -> [success: bb6, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+3:30: +3:38 + _24 = Shl(move _25, move _26); // scope 0 at $DIR/shifts.rs:+3:20: +3:28 + StorageDead(_26); // scope 0 at $DIR/shifts.rs:+3:27: +3:28 + StorageDead(_25); // scope 0 at $DIR/shifts.rs:+3:27: +3:28 + StorageLive(_28); // scope 0 at $DIR/shifts.rs:+3:30: +3:38 + StorageLive(_29); // scope 0 at $DIR/shifts.rs:+3:30: +3:33 + _29 = _2; // scope 0 at $DIR/shifts.rs:+3:30: +3:33 + StorageLive(_30); // scope 0 at $DIR/shifts.rs:+3:37: +3:38 + _30 = _5; // scope 0 at $DIR/shifts.rs:+3:37: +3:38 + _31 = Lt(_30, const 128_u128); // scope 0 at $DIR/shifts.rs:+3:30: +3:38 + assert(move _31, "attempt to shift left by `{}`, which would overflow", _30) -> [success: bb6, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+3:30: +3:38 } bb6: { - _33 = Shl(move _34, move _35); // scope 0 at $DIR/shifts.rs:+3:30: +3:38 - StorageDead(_35); // scope 0 at $DIR/shifts.rs:+3:37: +3:38 - StorageDead(_34); // scope 0 at $DIR/shifts.rs:+3:37: +3:38 - _22 = [move _23, move _28, move _33]; // scope 0 at $DIR/shifts.rs:+3:9: +3:39 - StorageDead(_33); // scope 0 at $DIR/shifts.rs:+3:38: +3:39 + _28 = Shl(move _29, move _30); // scope 0 at $DIR/shifts.rs:+3:30: +3:38 + StorageDead(_30); // scope 0 at $DIR/shifts.rs:+3:37: +3:38 + StorageDead(_29); // scope 0 at $DIR/shifts.rs:+3:37: +3:38 + _19 = [move _20, move _24, move _28]; // scope 0 at $DIR/shifts.rs:+3:9: +3:39 StorageDead(_28); // scope 0 at $DIR/shifts.rs:+3:38: +3:39 - StorageDead(_23); // scope 0 at $DIR/shifts.rs:+3:38: +3:39 - _0 = (move _6, move _22); // scope 0 at $DIR/shifts.rs:+1:5: +4:6 - StorageDead(_22); // scope 0 at $DIR/shifts.rs:+4:5: +4:6 + StorageDead(_24); // scope 0 at $DIR/shifts.rs:+3:38: +3:39 + StorageDead(_20); // scope 0 at $DIR/shifts.rs:+3:38: +3:39 + _0 = (move _6, move _19); // scope 0 at $DIR/shifts.rs:+1:5: +4:6 + StorageDead(_19); // scope 0 at $DIR/shifts.rs:+4:5: +4:6 StorageDead(_6); // scope 0 at $DIR/shifts.rs:+4:5: +4:6 return; // scope 0 at $DIR/shifts.rs:+5:2: +5:2 } diff --git a/tests/mir-opt/issue_101973.inner.ConstProp.diff b/tests/mir-opt/issue_101973.inner.ConstProp.diff index fb0b3866e696b..b377a65b96418 100644 --- a/tests/mir-opt/issue_101973.inner.ConstProp.diff +++ b/tests/mir-opt/issue_101973.inner.ConstProp.diff @@ -12,9 +12,9 @@ let mut _7: u32; // in scope 0 at $DIR/issue_101973.rs:+1:31: +1:52 let mut _8: u32; // in scope 0 at $DIR/issue_101973.rs:+1:32: +1:45 let mut _9: u32; // in scope 0 at $DIR/issue_101973.rs:+1:33: +1:39 - let mut _10: i32; // in scope 0 at $DIR/issue_101973.rs:+1:32: +1:45 + let mut _10: u32; // in scope 0 at $DIR/issue_101973.rs:+1:32: +1:45 let mut _11: bool; // in scope 0 at $DIR/issue_101973.rs:+1:32: +1:45 - let mut _12: i32; // in scope 0 at $DIR/issue_101973.rs:+1:31: +1:57 + let mut _12: u32; // in scope 0 at $DIR/issue_101973.rs:+1:31: +1:57 let mut _13: bool; // in scope 0 at $DIR/issue_101973.rs:+1:31: +1:57 scope 1 (inlined imm8) { // at $DIR/issue_101973.rs:14:5: 14:17 debug x => _1; // in scope 1 at $DIR/issue_101973.rs:5:13: 5:14 @@ -43,24 +43,24 @@ StorageLive(_6); // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57 StorageLive(_7); // scope 0 at $DIR/issue_101973.rs:+1:31: +1:52 StorageLive(_8); // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45 -- _10 = BitAnd(const 8_i32, const -32_i32); // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45 -- _11 = Ne(move _10, const 0_i32); // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45 -- assert(!move _11, "attempt to shift right by `{}`, which would overflow", const 8_i32) -> bb1; // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45 -+ _10 = const 0_i32; // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45 -+ _11 = const false; // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45 -+ assert(!const false, "attempt to shift right by `{}`, which would overflow", const 8_i32) -> bb1; // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45 +- _10 = const 8_i32 as u32 (IntToInt); // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45 +- _11 = Lt(move _10, const 32_u32); // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45 +- assert(move _11, "attempt to shift right by `{}`, which would overflow", const 8_i32) -> bb1; // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45 ++ _10 = const 8_u32; // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45 ++ _11 = const true; // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45 ++ assert(const true, "attempt to shift right by `{}`, which would overflow", const 8_i32) -> bb1; // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45 } bb1: { _8 = Shr(_1, const 8_i32); // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45 _7 = BitAnd(move _8, const 15_u32); // scope 0 at $DIR/issue_101973.rs:+1:31: +1:52 StorageDead(_8); // scope 0 at $DIR/issue_101973.rs:+1:51: +1:52 -- _12 = BitAnd(const 1_i32, const -32_i32); // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57 -- _13 = Ne(move _12, const 0_i32); // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57 -- assert(!move _13, "attempt to shift left by `{}`, which would overflow", const 1_i32) -> bb2; // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57 -+ _12 = const 0_i32; // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57 -+ _13 = const false; // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57 -+ assert(!const false, "attempt to shift left by `{}`, which would overflow", const 1_i32) -> bb2; // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57 +- _12 = const 1_i32 as u32 (IntToInt); // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57 +- _13 = Lt(move _12, const 32_u32); // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57 +- assert(move _13, "attempt to shift left by `{}`, which would overflow", const 1_i32) -> bb2; // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57 ++ _12 = const 1_u32; // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57 ++ _13 = const true; // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57 ++ assert(const true, "attempt to shift left by `{}`, which would overflow", const 1_i32) -> bb2; // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57 } bb2: { From e8be3d238695145830a2c7a9045ca53c5b0c1a6e Mon Sep 17 00:00:00 2001 From: Frank Steffahn Date: Wed, 15 Mar 2023 01:09:54 +0900 Subject: [PATCH 10/16] Stabilize `arc_into_inner` and `rc_into_inner`. Includes resolving the FIXMEs in the documentation, and some very minor documentation improvements. --- library/alloc/src/rc.rs | 6 +++--- library/alloc/src/sync.rs | 23 +++-------------------- 2 files changed, 6 insertions(+), 23 deletions(-) diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 089b6b6418dc1..1e9cf404f77ea 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -692,10 +692,10 @@ impl Rc { /// it is guaranteed that exactly one of the calls returns the inner value. /// This means in particular that the inner value is not dropped. /// - /// This is equivalent to `Rc::try_unwrap(...).ok()`. (Note that these are not equivalent for - /// `Arc`, due to race conditions that do not apply to `Rc`.) + /// This is equivalent to `Rc::try_unwrap(this).ok()`. (Note that these are not equivalent for + /// [`Arc`](crate::sync::Arc), due to race conditions that do not apply to `Rc`.) #[inline] - #[unstable(feature = "rc_into_inner", issue = "106894")] + #[stable(feature = "rc_into_inner", since = "CURRENT_RUSTC_VERSION")] pub fn into_inner(this: Self) -> Option { Rc::try_unwrap(this).ok() } diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 8a27a7ecdf653..150924851d21d 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -662,20 +662,17 @@ impl Arc { /// /// This will succeed even if there are outstanding weak references. /// - // FIXME: when `Arc::into_inner` is stabilized, add this paragraph: - /* /// It is strongly recommended to use [`Arc::into_inner`] instead if you don't /// want to keep the `Arc` in the [`Err`] case. /// Immediately dropping the [`Err`] payload, like in the expression /// `Arc::try_unwrap(this).ok()`, can still cause the strong count to /// drop to zero and the inner value of the `Arc` to be dropped: - /// For instance if two threads execute this expression in parallel, then + /// For instance if two threads each execute this expression in parallel, then /// there is a race condition. The threads could first both check whether they /// have the last clone of their `Arc` via `Arc::try_unwrap`, and then /// both drop their `Arc` in the call to [`ok`][`Result::ok`], /// taking the strong count from two down to zero. /// - */ /// # Examples /// /// ``` @@ -719,20 +716,13 @@ impl Arc { /// This means in particular that the inner value is not dropped. /// /// The similar expression `Arc::try_unwrap(this).ok()` does not - /// offer such a guarantee. See the last example below. - // - // FIXME: when `Arc::into_inner` is stabilized, add this to end - // of the previous sentence: - /* + /// offer such a guarantee. See the last example below /// and the documentation of [`Arc::try_unwrap`]. - */ /// /// # Examples /// /// Minimal example demonstrating the guarantee that `Arc::into_inner` gives. /// ``` - /// #![feature(arc_into_inner)] - /// /// use std::sync::Arc; /// /// let x = Arc::new(3); @@ -756,8 +746,6 @@ impl Arc { /// /// A more practical example demonstrating the need for `Arc::into_inner`: /// ``` - /// #![feature(arc_into_inner)] - /// /// use std::sync::Arc; /// /// // Definition of a simple singly linked list using `Arc`: @@ -807,13 +795,8 @@ impl Arc { /// x_thread.join().unwrap(); /// y_thread.join().unwrap(); /// ``` - - // FIXME: when `Arc::into_inner` is stabilized, adjust above documentation - // and the documentation of `Arc::try_unwrap` according to the `FIXME`s. Also - // open an issue on rust-lang/rust-clippy, asking for a lint against - // `Arc::try_unwrap(...).ok()`. #[inline] - #[unstable(feature = "arc_into_inner", issue = "106894")] + #[stable(feature = "arc_into_inner", since = "CURRENT_RUSTC_VERSION")] pub fn into_inner(this: Self) -> Option { // Make sure that the ordinary `Drop` implementation isn’t called as well let mut this = mem::ManuallyDrop::new(this); From 3f7aeb30ae966bf7a73735169b4243727f5c456b Mon Sep 17 00:00:00 2001 From: Boxy Date: Thu, 23 Mar 2023 00:07:55 +0000 Subject: [PATCH 11/16] make param bound vars visibly bound vars --- compiler/rustc_middle/src/ty/print/pretty.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index fffdbfc9660bb..659c50a392ecd 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -704,7 +704,11 @@ pub trait PrettyPrinter<'tcx>: ty::BoundTyKind::Anon(bv) => { self.pretty_print_bound_var(debruijn, ty::BoundVar::from_u32(bv))? } - ty::BoundTyKind::Param(_, s) => p!(write("{}", s)), + ty::BoundTyKind::Param(_, s) => match self.should_print_verbose() { + true if debruijn == ty::INNERMOST => p!(write("^{}", s)), + true => p!(write("^{}_{}", debruijn.index(), s)), + false => p!(write("{}", s)), + }, }, ty::Adt(def, substs) => { p!(print_def_path(def.did(), substs)); From 5dc3fd7c05010654b4d80b87eac8c937e4808607 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 21 Mar 2023 21:50:16 +0000 Subject: [PATCH 12/16] Include relation direction in AliasEq predicate --- compiler/rustc_infer/src/infer/combine.rs | 8 +- compiler/rustc_infer/src/infer/equate.rs | 4 + compiler/rustc_infer/src/infer/glb.rs | 5 + compiler/rustc_infer/src/infer/lub.rs | 5 + .../rustc_infer/src/infer/nll_relate/mod.rs | 10 ++ compiler/rustc_infer/src/infer/sub.rs | 4 + compiler/rustc_middle/src/ty/flags.rs | 2 +- compiler/rustc_middle/src/ty/mod.rs | 24 ++++- compiler/rustc_middle/src/ty/print/pretty.rs | 3 +- .../rustc_middle/src/ty/structural_impls.rs | 4 +- compiler/rustc_privacy/src/lib.rs | 2 +- .../src/solve/eval_ctxt.rs | 4 +- .../src/solve/fulfill.rs | 2 +- .../rustc_trait_selection/src/solve/mod.rs | 95 ++++++++++++++----- .../traits/error_reporting/method_chain.rs | 5 + tests/ui/traits/new-solver/alias-sub.rs | 34 +++++++ 16 files changed, 175 insertions(+), 36 deletions(-) create mode 100644 tests/ui/traits/new-solver/alias-sub.rs diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs index 4503af03ca341..c82438f05e140 100644 --- a/compiler/rustc_infer/src/infer/combine.rs +++ b/compiler/rustc_infer/src/infer/combine.rs @@ -842,7 +842,7 @@ pub trait ObligationEmittingRelation<'tcx>: TypeRelation<'tcx> { let (a, b) = if self.a_is_expected() { (a, b) } else { (b, a) }; self.register_predicates([ty::Binder::dummy(if self.tcx().trait_solver_next() { - ty::PredicateKind::AliasEq(a.into(), b.into()) + ty::PredicateKind::AliasEq(a.into(), b.into(), ty::AliasRelationDirection::Equate) } else { ty::PredicateKind::ConstEquate(a, b) })]); @@ -852,13 +852,15 @@ pub trait ObligationEmittingRelation<'tcx>: TypeRelation<'tcx> { /// /// If they aren't equal then the relation doesn't hold. fn register_type_equate_obligation(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) { - let (a, b) = if self.a_is_expected() { (a, b) } else { (b, a) }; - self.register_predicates([ty::Binder::dummy(ty::PredicateKind::AliasEq( a.into(), b.into(), + self.alias_relate_direction(), ))]); } + + /// Relation direction emitted for `AliasEq` predicates + fn alias_relate_direction(&self) -> ty::AliasRelationDirection; } fn int_unification_error<'tcx>( diff --git a/compiler/rustc_infer/src/infer/equate.rs b/compiler/rustc_infer/src/infer/equate.rs index c92a74b6241a6..38002357cde35 100644 --- a/compiler/rustc_infer/src/infer/equate.rs +++ b/compiler/rustc_infer/src/infer/equate.rs @@ -210,4 +210,8 @@ impl<'tcx> ObligationEmittingRelation<'tcx> for Equate<'_, '_, 'tcx> { fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) { self.fields.register_obligations(obligations); } + + fn alias_relate_direction(&self) -> ty::AliasRelationDirection { + ty::AliasRelationDirection::Equate + } } diff --git a/compiler/rustc_infer/src/infer/glb.rs b/compiler/rustc_infer/src/infer/glb.rs index 5c12351226aa5..6395c4d4b2078 100644 --- a/compiler/rustc_infer/src/infer/glb.rs +++ b/compiler/rustc_infer/src/infer/glb.rs @@ -155,4 +155,9 @@ impl<'tcx> ObligationEmittingRelation<'tcx> for Glb<'_, '_, 'tcx> { fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) { self.fields.register_obligations(obligations); } + + fn alias_relate_direction(&self) -> ty::AliasRelationDirection { + // FIXME(deferred_projection_equality): This isn't right, I think? + ty::AliasRelationDirection::Equate + } } diff --git a/compiler/rustc_infer/src/infer/lub.rs b/compiler/rustc_infer/src/infer/lub.rs index dbef42db8f1bf..98cbd4c561c52 100644 --- a/compiler/rustc_infer/src/infer/lub.rs +++ b/compiler/rustc_infer/src/infer/lub.rs @@ -155,4 +155,9 @@ impl<'tcx> ObligationEmittingRelation<'tcx> for Lub<'_, '_, 'tcx> { fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) { self.fields.register_obligations(obligations) } + + fn alias_relate_direction(&self) -> ty::AliasRelationDirection { + // FIXME(deferred_projection_equality): This isn't right, I think? + ty::AliasRelationDirection::Equate + } } diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs index 573cd91a2a2a6..216d2965da761 100644 --- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs +++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs @@ -777,6 +777,16 @@ where fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) { self.delegate.register_obligations(obligations); } + + fn alias_relate_direction(&self) -> ty::AliasRelationDirection { + match self.ambient_variance { + ty::Variance::Covariant => ty::AliasRelationDirection::Subtype, + ty::Variance::Contravariant => ty::AliasRelationDirection::Supertype, + ty::Variance::Invariant => ty::AliasRelationDirection::Equate, + // FIXME(deferred_projection_equality): Implement this when we trigger it + ty::Variance::Bivariant => unreachable!(), + } + } } /// When we encounter a binder like `for<..> fn(..)`, we actually have diff --git a/compiler/rustc_infer/src/infer/sub.rs b/compiler/rustc_infer/src/infer/sub.rs index 230cadb11842e..fc73ca7606d23 100644 --- a/compiler/rustc_infer/src/infer/sub.rs +++ b/compiler/rustc_infer/src/infer/sub.rs @@ -236,4 +236,8 @@ impl<'tcx> ObligationEmittingRelation<'tcx> for Sub<'_, '_, 'tcx> { fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) { self.fields.register_obligations(obligations); } + + fn alias_relate_direction(&self) -> ty::AliasRelationDirection { + ty::AliasRelationDirection::Subtype + } } diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index 91241ff404f4c..1ae47fddccc1a 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -288,7 +288,7 @@ impl FlagComputation { self.add_ty(ty); } ty::PredicateKind::Ambiguous => {} - ty::PredicateKind::AliasEq(t1, t2) => { + ty::PredicateKind::AliasEq(t1, t2, _) => { self.add_term(t1); self.add_term(t2); } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index d383a41320819..d1e268f49c4b2 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -640,7 +640,25 @@ pub enum PredicateKind<'tcx> { /// This predicate requires two terms to be equal to eachother. /// /// Only used for new solver - AliasEq(Term<'tcx>, Term<'tcx>), + AliasEq(Term<'tcx>, Term<'tcx>, AliasRelationDirection), +} + +#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] +#[derive(HashStable, Debug)] +pub enum AliasRelationDirection { + Equate, + Subtype, + Supertype, +} + +impl AliasRelationDirection { + pub fn invert(self) -> Self { + match self { + AliasRelationDirection::Equate => AliasRelationDirection::Equate, + AliasRelationDirection::Subtype => AliasRelationDirection::Supertype, + AliasRelationDirection::Supertype => AliasRelationDirection::Subtype, + } + } } /// The crate outlives map is computed during typeck and contains the @@ -976,11 +994,11 @@ impl<'tcx> Term<'tcx> { } } - /// This function returns `None` for `AliasKind::Opaque`. + /// This function returns the inner `AliasTy` if this term is a projection. /// /// FIXME: rename `AliasTy` to `AliasTerm` and make sure we correctly /// deal with constants. - pub fn to_alias_term_no_opaque(&self, tcx: TyCtxt<'tcx>) -> Option> { + pub fn to_projection_term(&self, tcx: TyCtxt<'tcx>) -> Option> { match self.unpack() { TermKind::Ty(ty) => match ty.kind() { ty::Alias(kind, alias_ty) => match kind { diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index fffdbfc9660bb..e96856231cec4 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -2847,7 +2847,8 @@ define_print_and_forward_display! { p!("the type `", print(ty), "` is found in the environment") } ty::PredicateKind::Ambiguous => p!("ambiguous"), - ty::PredicateKind::AliasEq(t1, t2) => p!(print(t1), " == ", print(t2)), + // TODO + ty::PredicateKind::AliasEq(t1, t2, _) => p!(print(t1), " == ", print(t2)), } } diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index ef643531bb288..92a2b4b18dd6a 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -177,7 +177,8 @@ impl<'tcx> fmt::Debug for ty::PredicateKind<'tcx> { write!(f, "TypeWellFormedFromEnv({:?})", ty) } ty::PredicateKind::Ambiguous => write!(f, "Ambiguous"), - ty::PredicateKind::AliasEq(t1, t2) => write!(f, "AliasEq({t1:?}, {t2:?})"), + // TODO + ty::PredicateKind::AliasEq(t1, t2, _) => write!(f, "AliasEq({t1:?}, {t2:?})"), } } } @@ -250,6 +251,7 @@ TrivialTypeTraversalAndLiftImpls! { crate::ty::AssocItem, crate::ty::AssocKind, crate::ty::AliasKind, + crate::ty::AliasRelationDirection, crate::ty::Placeholder, crate::ty::Placeholder, crate::ty::ClosureKind, diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index d884ebd9acc73..fda9ef008d715 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -180,7 +180,7 @@ where | ty::PredicateKind::ConstEquate(_, _) | ty::PredicateKind::TypeWellFormedFromEnv(_) | ty::PredicateKind::Ambiguous - | ty::PredicateKind::AliasEq(_, _) => bug!("unexpected predicate: {:?}", predicate), + | ty::PredicateKind::AliasEq(..) => bug!("unexpected predicate: {:?}", predicate), } } diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs index 9541292235795..106a989b22f61 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs @@ -223,8 +223,8 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { ty::PredicateKind::TypeWellFormedFromEnv(..) => { bug!("TypeWellFormedFromEnv is only used for Chalk") } - ty::PredicateKind::AliasEq(lhs, rhs) => { - self.compute_alias_eq_goal(Goal { param_env, predicate: (lhs, rhs) }) + ty::PredicateKind::AliasEq(lhs, rhs, direction) => { + self.compute_alias_eq_goal(Goal { param_env, predicate: (lhs, rhs, direction) }) } } } else { diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index 38120b9760f3d..a9c9e5761a86d 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -73,7 +73,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> { MismatchedProjectionTypes { err: TypeError::Mismatch }, ) } - ty::PredicateKind::AliasEq(_, _) => { + ty::PredicateKind::AliasEq(_, _, _) => { FulfillmentErrorCode::CodeProjectionError( MismatchedProjectionTypes { err: TypeError::Mismatch }, ) diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index 606c2eaa51051..48ef089a7b2ec 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -158,13 +158,35 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { #[instrument(level = "debug", skip(self), ret)] fn compute_alias_eq_goal( &mut self, - goal: Goal<'tcx, (ty::Term<'tcx>, ty::Term<'tcx>)>, + goal: Goal<'tcx, (ty::Term<'tcx>, ty::Term<'tcx>, ty::AliasRelationDirection)>, ) -> QueryResult<'tcx> { let tcx = self.tcx(); - let evaluate_normalizes_to = |ecx: &mut EvalCtxt<'_, 'tcx>, alias, other| { + let evaluate_normalizes_to = |ecx: &mut EvalCtxt<'_, 'tcx>, alias, other, direction| { debug!("evaluate_normalizes_to(alias={:?}, other={:?})", alias, other); - let r = ecx.probe(|ecx| { + let result = ecx.probe(|ecx| { + let other = match direction { + // This is purely an optimization. + ty::AliasRelationDirection::Equate => other, + + ty::AliasRelationDirection::Subtype | ty::AliasRelationDirection::Supertype => { + let fresh = ecx.next_term_infer_of_kind(other); + let (sub, sup) = if direction == ty::AliasRelationDirection::Subtype { + (fresh, other) + } else { + (other, fresh) + }; + ecx.add_goals( + ecx.infcx + .at(&ObligationCause::dummy(), goal.param_env) + .sub(DefineOpaqueTypes::No, sub, sup)? + .into_obligations() + .into_iter() + .map(|o| o.into()), + ); + fresh + } + }; ecx.add_goal(goal.with( tcx, ty::Binder::dummy(ty::ProjectionPredicate { @@ -174,37 +196,64 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { )); ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }); - debug!("evaluate_normalizes_to(..) -> {:?}", r); - r + debug!("evaluate_normalizes_to({alias}, {other}, {direction:?}) -> {result:?}"); + result }; - if goal.predicate.0.is_infer() || goal.predicate.1.is_infer() { + let (lhs, rhs, direction) = goal.predicate; + + if lhs.is_infer() || rhs.is_infer() { bug!( "`AliasEq` goal with an infer var on lhs or rhs which should have been instantiated" ); } - match ( - goal.predicate.0.to_alias_term_no_opaque(tcx), - goal.predicate.1.to_alias_term_no_opaque(tcx), - ) { + match (lhs.to_projection_term(tcx), rhs.to_projection_term(tcx)) { (None, None) => bug!("`AliasEq` goal without an alias on either lhs or rhs"), - (Some(alias), None) => evaluate_normalizes_to(self, alias, goal.predicate.1), - (None, Some(alias)) => evaluate_normalizes_to(self, alias, goal.predicate.0), - (Some(alias_lhs), Some(alias_rhs)) => { - debug!("compute_alias_eq_goal: both sides are aliases"); - let mut candidates = Vec::with_capacity(3); + // RHS is not a projection, only way this is true is if LHS normalizes-to RHS + (Some(alias_lhs), None) => evaluate_normalizes_to(self, alias_lhs, rhs, direction), - // Evaluate all 3 potential candidates for the alias' being equal - candidates.push(evaluate_normalizes_to(self, alias_lhs, goal.predicate.1)); - candidates.push(evaluate_normalizes_to(self, alias_rhs, goal.predicate.0)); - candidates.push(self.probe(|ecx| { - debug!("compute_alias_eq_goal: alias defids are equal, equating substs"); - ecx.eq(goal.param_env, alias_lhs, alias_rhs)?; - ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) - })); + // LHS is not a projection, only way this is true is if RHS normalizes-to LHS + (None, Some(alias_rhs)) => { + evaluate_normalizes_to(self, alias_rhs, lhs, direction.invert()) + } + (Some(alias_lhs), Some(alias_rhs)) => { + debug!("compute_alias_eq_goal: both sides are aliases"); + + let candidates = vec![ + // LHS normalizes-to RHS + evaluate_normalizes_to(self, alias_lhs, rhs, direction), + // RHS normalizes-to RHS + evaluate_normalizes_to(self, alias_rhs, lhs, direction.invert()), + // Relate via substs + self.probe(|ecx| { + debug!("compute_alias_eq_goal: alias defids are equal, equating substs"); + + ecx.add_goals( + match direction { + ty::AliasRelationDirection::Equate => ecx + .infcx + .at(&ObligationCause::dummy(), goal.param_env) + .eq(DefineOpaqueTypes::No, alias_lhs, alias_rhs), + ty::AliasRelationDirection::Subtype => ecx + .infcx + .at(&ObligationCause::dummy(), goal.param_env) + .sub(DefineOpaqueTypes::No, alias_lhs, alias_rhs), + ty::AliasRelationDirection::Supertype => ecx + .infcx + .at(&ObligationCause::dummy(), goal.param_env) + .sup(DefineOpaqueTypes::No, alias_lhs, alias_rhs), + }? + .into_obligations() + .into_iter() + .map(|o| o.into()), + ); + + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + }), + ]; debug!(?candidates); self.try_merge_responses(candidates.into_iter()) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/method_chain.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/method_chain.rs index 1174efdbfa8fa..13607b9079a75 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/method_chain.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/method_chain.rs @@ -92,6 +92,11 @@ impl<'a, 'tcx> TypeRelation<'tcx> for CollectAllMismatches<'a, 'tcx> { } impl<'tcx> ObligationEmittingRelation<'tcx> for CollectAllMismatches<'_, 'tcx> { + fn alias_relate_direction(&self) -> ty::AliasRelationDirection { + // FIXME(deferred_projection_equality): We really should get rid of this relation. + ty::AliasRelationDirection::Equate + } + fn register_obligations(&mut self, _obligations: PredicateObligations<'tcx>) { // FIXME(deferred_projection_equality) } diff --git a/tests/ui/traits/new-solver/alias-sub.rs b/tests/ui/traits/new-solver/alias-sub.rs new file mode 100644 index 0000000000000..30c1981a92ece --- /dev/null +++ b/tests/ui/traits/new-solver/alias-sub.rs @@ -0,0 +1,34 @@ +// compile-flags: -Ztrait-solver=next +// check-pass + +trait Trait { + type Assoc: Sized; +} + +impl Trait for &'static str { + type Assoc = &'static str; +} + +// Wrapper is just here to get around stupid `Sized` obligations in mir typeck +struct Wrapper(std::marker::PhantomData); +fn mk(x: T) -> Wrapper<::Assoc> { todo!() } + + +trait IsStaticStr {} +impl IsStaticStr for (&'static str,) {} +fn define(_: T) {} + +fn foo<'a, T: Trait>() { + let y = Default::default(); + + // `::Assoc <: &'a str` + // In the old solver, this would *equate* the LHS and RHS. + let _: Wrapper<&'a str> = mk(y); + + // ... then later on, we constrain `?0 = &'static str` + // but that should not mean that `'a = 'static`, because + // we should use *sub* above. + define((y,)); +} + +fn main() {} From 3a36a093ddb1c117247a8154970d5f8a5782da87 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 21 Mar 2023 22:11:40 +0000 Subject: [PATCH 13/16] Rename AliasEq -> AliasRelate --- compiler/rustc_hir_analysis/src/astconv/mod.rs | 2 +- .../src/impl_wf_check/min_specialization.rs | 2 +- compiler/rustc_hir_analysis/src/outlives/explicit.rs | 2 +- compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs | 2 +- compiler/rustc_hir_typeck/src/method/probe.rs | 2 +- compiler/rustc_infer/src/infer/combine.rs | 6 +++--- compiler/rustc_infer/src/infer/outlives/mod.rs | 2 +- compiler/rustc_infer/src/infer/projection.rs | 2 +- compiler/rustc_infer/src/traits/util.rs | 2 +- compiler/rustc_lint/src/builtin.rs | 2 +- compiler/rustc_middle/src/ty/flags.rs | 2 +- compiler/rustc_middle/src/ty/mod.rs | 10 +++++----- compiler/rustc_middle/src/ty/print/pretty.rs | 2 +- compiler/rustc_middle/src/ty/structural_impls.rs | 2 +- compiler/rustc_privacy/src/lib.rs | 2 +- .../rustc_trait_selection/src/solve/eval_ctxt.rs | 8 +++++--- compiler/rustc_trait_selection/src/solve/fulfill.rs | 2 +- compiler/rustc_trait_selection/src/solve/mod.rs | 12 +++++++----- .../rustc_trait_selection/src/traits/auto_trait.rs | 2 +- .../src/traits/error_reporting/mod.rs | 4 ++-- compiler/rustc_trait_selection/src/traits/fulfill.rs | 8 ++++---- .../src/traits/object_safety.rs | 4 ++-- .../rustc_trait_selection/src/traits/select/mod.rs | 4 ++-- compiler/rustc_trait_selection/src/traits/wf.rs | 6 +++--- compiler/rustc_traits/src/chalk/lowering.rs | 8 ++++---- compiler/rustc_traits/src/implied_outlives_bounds.rs | 4 ++-- .../rustc_traits/src/normalize_erasing_regions.rs | 2 +- src/librustdoc/clean/mod.rs | 2 +- .../clippy/clippy_utils/src/qualify_min_const_fn.rs | 2 +- 29 files changed, 57 insertions(+), 53 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 8a9aac14fb65f..703c845eafa28 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -1335,7 +1335,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ty::Clause::RegionOutlives(_) | ty::Clause::ConstArgHasType(..) => bug!(), }, ty::PredicateKind::WellFormed(_) - | ty::PredicateKind::AliasEq(..) + | ty::PredicateKind::AliasRelate(..) | ty::PredicateKind::ObjectSafe(_) | ty::PredicateKind::ClosureKind(_, _, _) | ty::PredicateKind::Subtype(_) diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs index 91c64eeec1eba..7f1e4ccc9647b 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs @@ -528,7 +528,7 @@ fn trait_predicate_kind<'tcx>( | ty::PredicateKind::Clause(ty::Clause::TypeOutlives(_)) | ty::PredicateKind::Clause(ty::Clause::Projection(_)) | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) - | ty::PredicateKind::AliasEq(..) + | ty::PredicateKind::AliasRelate(..) | ty::PredicateKind::WellFormed(_) | ty::PredicateKind::Subtype(_) | ty::PredicateKind::Coerce(_) diff --git a/compiler/rustc_hir_analysis/src/outlives/explicit.rs b/compiler/rustc_hir_analysis/src/outlives/explicit.rs index 9ee6785970c46..357deb07b8f31 100644 --- a/compiler/rustc_hir_analysis/src/outlives/explicit.rs +++ b/compiler/rustc_hir_analysis/src/outlives/explicit.rs @@ -56,7 +56,7 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> { | ty::PredicateKind::Clause(ty::Clause::Projection(..)) | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) | ty::PredicateKind::WellFormed(..) - | ty::PredicateKind::AliasEq(..) + | ty::PredicateKind::AliasRelate(..) | ty::PredicateKind::ObjectSafe(..) | ty::PredicateKind::ClosureKind(..) | ty::PredicateKind::Subtype(..) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 8455076de5634..3def97bca4789 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -666,7 +666,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | ty::PredicateKind::Clause(ty::Clause::TypeOutlives(..)) | ty::PredicateKind::WellFormed(..) | ty::PredicateKind::ObjectSafe(..) - | ty::PredicateKind::AliasEq(..) + | ty::PredicateKind::AliasRelate(..) | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) // N.B., this predicate is created by breaking down a diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index b6d39341fe7cc..0eff5c956ef64 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -838,7 +838,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) | ty::PredicateKind::Ambiguous - | ty::PredicateKind::AliasEq(..) + | ty::PredicateKind::AliasRelate(..) | ty::PredicateKind::TypeWellFormedFromEnv(..) => None, } }); diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs index c82438f05e140..3fadc243dcd7a 100644 --- a/compiler/rustc_infer/src/infer/combine.rs +++ b/compiler/rustc_infer/src/infer/combine.rs @@ -842,7 +842,7 @@ pub trait ObligationEmittingRelation<'tcx>: TypeRelation<'tcx> { let (a, b) = if self.a_is_expected() { (a, b) } else { (b, a) }; self.register_predicates([ty::Binder::dummy(if self.tcx().trait_solver_next() { - ty::PredicateKind::AliasEq(a.into(), b.into(), ty::AliasRelationDirection::Equate) + ty::PredicateKind::AliasRelate(a.into(), b.into(), ty::AliasRelationDirection::Equate) } else { ty::PredicateKind::ConstEquate(a, b) })]); @@ -852,14 +852,14 @@ pub trait ObligationEmittingRelation<'tcx>: TypeRelation<'tcx> { /// /// If they aren't equal then the relation doesn't hold. fn register_type_equate_obligation(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) { - self.register_predicates([ty::Binder::dummy(ty::PredicateKind::AliasEq( + self.register_predicates([ty::Binder::dummy(ty::PredicateKind::AliasRelate( a.into(), b.into(), self.alias_relate_direction(), ))]); } - /// Relation direction emitted for `AliasEq` predicates + /// Relation direction emitted for `AliasRelate` predicates fn alias_relate_direction(&self) -> ty::AliasRelationDirection; } diff --git a/compiler/rustc_infer/src/infer/outlives/mod.rs b/compiler/rustc_infer/src/infer/outlives/mod.rs index 83f3d5a74fb48..048dad3a48bc2 100644 --- a/compiler/rustc_infer/src/infer/outlives/mod.rs +++ b/compiler/rustc_infer/src/infer/outlives/mod.rs @@ -22,7 +22,7 @@ pub fn explicit_outlives_bounds<'tcx>( ty::PredicateKind::Clause(ty::Clause::Projection(..)) | ty::PredicateKind::Clause(ty::Clause::Trait(..)) | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) - | ty::PredicateKind::AliasEq(..) + | ty::PredicateKind::AliasRelate(..) | ty::PredicateKind::Coerce(..) | ty::PredicateKind::Subtype(..) | ty::PredicateKind::WellFormed(..) diff --git a/compiler/rustc_infer/src/infer/projection.rs b/compiler/rustc_infer/src/infer/projection.rs index f795047709e40..fa6529dfa93ec 100644 --- a/compiler/rustc_infer/src/infer/projection.rs +++ b/compiler/rustc_infer/src/infer/projection.rs @@ -26,7 +26,7 @@ impl<'tcx> InferCtxt<'tcx> { // completely change the normalization routine with the new solver. // // The new solver correctly handles projection equality so this hack - // is not necessary. if re-enabled it should emit `PredicateKind::AliasEq` + // is not necessary. if re-enabled it should emit `PredicateKind::AliasRelate` // not `PredicateKind::Clause(Clause::Projection(..))` as in the new solver // `Projection` is used as `normalizes-to` which will fail for `::Assoc eq ?0`. return projection_ty.to_ty(self.tcx); diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs index c07ff51657994..0d2faeba5fc0f 100644 --- a/compiler/rustc_infer/src/traits/util.rs +++ b/compiler/rustc_infer/src/traits/util.rs @@ -293,7 +293,7 @@ impl<'tcx> Elaborator<'tcx> { // Nothing to elaborate } ty::PredicateKind::Ambiguous => {} - ty::PredicateKind::AliasEq(..) => { + ty::PredicateKind::AliasRelate(..) => { // No } ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) => { diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 8af1a663ef5e3..f8dd8299312d8 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -1601,7 +1601,7 @@ impl<'tcx> LateLintPass<'tcx> for TrivialConstraints { // Ignore projections, as they can only be global // if the trait bound is global Clause(Clause::Projection(..)) | - AliasEq(..) | + AliasRelate(..) | // Ignore bounds that a user can't type WellFormed(..) | ObjectSafe(..) | diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index 1ae47fddccc1a..5a6ee1238112c 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -288,7 +288,7 @@ impl FlagComputation { self.add_ty(ty); } ty::PredicateKind::Ambiguous => {} - ty::PredicateKind::AliasEq(t1, t2, _) => { + ty::PredicateKind::AliasRelate(t1, t2, _) => { self.add_term(t1); self.add_term(t2); } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index d1e268f49c4b2..4ab3df917e34c 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -543,7 +543,7 @@ impl<'tcx> Predicate<'tcx> { | PredicateKind::Clause(Clause::TypeOutlives(_)) | PredicateKind::Clause(Clause::Projection(_)) | PredicateKind::Clause(Clause::ConstArgHasType(..)) - | PredicateKind::AliasEq(..) + | PredicateKind::AliasRelate(..) | PredicateKind::ObjectSafe(_) | PredicateKind::ClosureKind(_, _, _) | PredicateKind::Subtype(_) @@ -640,7 +640,7 @@ pub enum PredicateKind<'tcx> { /// This predicate requires two terms to be equal to eachother. /// /// Only used for new solver - AliasEq(Term<'tcx>, Term<'tcx>, AliasRelationDirection), + AliasRelate(Term<'tcx>, Term<'tcx>, AliasRelationDirection), } #[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] @@ -1224,7 +1224,7 @@ impl<'tcx> Predicate<'tcx> { PredicateKind::Clause(Clause::Trait(t)) => Some(predicate.rebind(t)), PredicateKind::Clause(Clause::Projection(..)) | PredicateKind::Clause(Clause::ConstArgHasType(..)) - | PredicateKind::AliasEq(..) + | PredicateKind::AliasRelate(..) | PredicateKind::Subtype(..) | PredicateKind::Coerce(..) | PredicateKind::Clause(Clause::RegionOutlives(..)) @@ -1245,7 +1245,7 @@ impl<'tcx> Predicate<'tcx> { PredicateKind::Clause(Clause::Projection(t)) => Some(predicate.rebind(t)), PredicateKind::Clause(Clause::Trait(..)) | PredicateKind::Clause(Clause::ConstArgHasType(..)) - | PredicateKind::AliasEq(..) + | PredicateKind::AliasRelate(..) | PredicateKind::Subtype(..) | PredicateKind::Coerce(..) | PredicateKind::Clause(Clause::RegionOutlives(..)) @@ -1267,7 +1267,7 @@ impl<'tcx> Predicate<'tcx> { PredicateKind::Clause(Clause::Trait(..)) | PredicateKind::Clause(Clause::ConstArgHasType(..)) | PredicateKind::Clause(Clause::Projection(..)) - | PredicateKind::AliasEq(..) + | PredicateKind::AliasRelate(..) | PredicateKind::Subtype(..) | PredicateKind::Coerce(..) | PredicateKind::Clause(Clause::RegionOutlives(..)) diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index e96856231cec4..ad5c9d93b4704 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -2848,7 +2848,7 @@ define_print_and_forward_display! { } ty::PredicateKind::Ambiguous => p!("ambiguous"), // TODO - ty::PredicateKind::AliasEq(t1, t2, _) => p!(print(t1), " == ", print(t2)), + ty::PredicateKind::AliasRelate(t1, t2, _) => p!(print(t1), " == ", print(t2)), } } diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 92a2b4b18dd6a..ad5f33d34dc2c 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -178,7 +178,7 @@ impl<'tcx> fmt::Debug for ty::PredicateKind<'tcx> { } ty::PredicateKind::Ambiguous => write!(f, "Ambiguous"), // TODO - ty::PredicateKind::AliasEq(t1, t2, _) => write!(f, "AliasEq({t1:?}, {t2:?})"), + ty::PredicateKind::AliasRelate(t1, t2, _) => write!(f, "AliasRelate({t1:?}, {t2:?})"), } } } diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index fda9ef008d715..3be0160d56173 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -180,7 +180,7 @@ where | ty::PredicateKind::ConstEquate(_, _) | ty::PredicateKind::TypeWellFormedFromEnv(_) | ty::PredicateKind::Ambiguous - | ty::PredicateKind::AliasEq(..) => bug!("unexpected predicate: {:?}", predicate), + | ty::PredicateKind::AliasRelate(..) => bug!("unexpected predicate: {:?}", predicate), } } diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs index 106a989b22f61..4cfea28475732 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs @@ -223,9 +223,11 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { ty::PredicateKind::TypeWellFormedFromEnv(..) => { bug!("TypeWellFormedFromEnv is only used for Chalk") } - ty::PredicateKind::AliasEq(lhs, rhs, direction) => { - self.compute_alias_eq_goal(Goal { param_env, predicate: (lhs, rhs, direction) }) - } + ty::PredicateKind::AliasRelate(lhs, rhs, direction) => self + .compute_alias_relate_goal(Goal { + param_env, + predicate: (lhs, rhs, direction), + }), } } else { let kind = self.infcx.instantiate_binder_with_placeholders(kind); diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index a9c9e5761a86d..01f171762ab67 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -73,7 +73,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> { MismatchedProjectionTypes { err: TypeError::Mismatch }, ) } - ty::PredicateKind::AliasEq(_, _, _) => { + ty::PredicateKind::AliasRelate(_, _, _) => { FulfillmentErrorCode::CodeProjectionError( MismatchedProjectionTypes { err: TypeError::Mismatch }, ) diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index 48ef089a7b2ec..5cda9da3c5a31 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -156,7 +156,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { } #[instrument(level = "debug", skip(self), ret)] - fn compute_alias_eq_goal( + fn compute_alias_relate_goal( &mut self, goal: Goal<'tcx, (ty::Term<'tcx>, ty::Term<'tcx>, ty::AliasRelationDirection)>, ) -> QueryResult<'tcx> { @@ -204,12 +204,12 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { if lhs.is_infer() || rhs.is_infer() { bug!( - "`AliasEq` goal with an infer var on lhs or rhs which should have been instantiated" + "`AliasRelate` goal with an infer var on lhs or rhs which should have been instantiated" ); } match (lhs.to_projection_term(tcx), rhs.to_projection_term(tcx)) { - (None, None) => bug!("`AliasEq` goal without an alias on either lhs or rhs"), + (None, None) => bug!("`AliasRelate` goal without an alias on either lhs or rhs"), // RHS is not a projection, only way this is true is if LHS normalizes-to RHS (Some(alias_lhs), None) => evaluate_normalizes_to(self, alias_lhs, rhs, direction), @@ -220,7 +220,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { } (Some(alias_lhs), Some(alias_rhs)) => { - debug!("compute_alias_eq_goal: both sides are aliases"); + debug!("compute_alias_relate_goal: both sides are aliases"); let candidates = vec![ // LHS normalizes-to RHS @@ -229,7 +229,9 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { evaluate_normalizes_to(self, alias_rhs, lhs, direction.invert()), // Relate via substs self.probe(|ecx| { - debug!("compute_alias_eq_goal: alias defids are equal, equating substs"); + debug!( + "compute_alias_relate_goal: alias defids are equal, equating substs" + ); ecx.add_goals( match direction { diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index dbf6775afc2fc..6b3a59b1ed545 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -832,7 +832,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { // the `ParamEnv`. ty::PredicateKind::WellFormed(..) | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) - | ty::PredicateKind::AliasEq(..) + | ty::PredicateKind::AliasRelate(..) | ty::PredicateKind::ObjectSafe(..) | ty::PredicateKind::ClosureKind(..) | ty::PredicateKind::Subtype(..) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 41ffaeeac1c11..617d53b609dbc 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1276,9 +1276,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { "TypeWellFormedFromEnv predicate should only exist in the environment" ), - ty::PredicateKind::AliasEq(..) => span_bug!( + ty::PredicateKind::AliasRelate(..) => span_bug!( span, - "AliasEq predicate should never be the predicate cause of a SelectionError" + "AliasRelate predicate should never be the predicate cause of a SelectionError" ), ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => { diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 23754480fcfb0..07e31e87bfb46 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -361,8 +361,8 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { ty::PredicateKind::TypeWellFormedFromEnv(..) => { bug!("TypeWellFormedFromEnv is only used for Chalk") } - ty::PredicateKind::AliasEq(..) => { - bug!("AliasEq is only used for new solver") + ty::PredicateKind::AliasRelate(..) => { + bug!("AliasRelate is only used for new solver") } }, Some(pred) => match pred { @@ -630,8 +630,8 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { ty::PredicateKind::TypeWellFormedFromEnv(..) => { bug!("TypeWellFormedFromEnv is only used for Chalk") } - ty::PredicateKind::AliasEq(..) => { - bug!("AliasEq is only used for new solver") + ty::PredicateKind::AliasRelate(..) => { + bug!("AliasRelate is only used for new solver") } ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => { match self.selcx.infcx.at(&obligation.cause, obligation.param_env).eq( diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 038f8964471f5..5d2af5ff33c8f 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -335,7 +335,7 @@ fn predicate_references_self<'tcx>( has_self_ty(&ty.into()).then_some(sp) } - ty::PredicateKind::AliasEq(..) => bug!("`AliasEq` not allowed as assumption"), + ty::PredicateKind::AliasRelate(..) => bug!("`AliasRelate` not allowed as assumption"), ty::PredicateKind::WellFormed(..) | ty::PredicateKind::ObjectSafe(..) @@ -395,7 +395,7 @@ fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool { | ty::PredicateKind::Clause(ty::Clause::TypeOutlives(..)) | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) - | ty::PredicateKind::AliasEq(..) + | ty::PredicateKind::AliasRelate(..) | ty::PredicateKind::Ambiguous | ty::PredicateKind::TypeWellFormedFromEnv(..) => false, } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index b8758ad93231d..bffefdf359ad5 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -977,8 +977,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::PredicateKind::TypeWellFormedFromEnv(..) => { bug!("TypeWellFormedFromEnv is only used for chalk") } - ty::PredicateKind::AliasEq(..) => { - bug!("AliasEq is only used for new solver") + ty::PredicateKind::AliasRelate(..) => { + bug!("AliasRelate is only used for new solver") } ty::PredicateKind::Ambiguous => Ok(EvaluatedToAmbig), ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => { diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index d498af359c584..ec5bd982a3c98 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -191,8 +191,8 @@ pub fn predicate_obligations<'tcx>( ty::PredicateKind::TypeWellFormedFromEnv(..) => { bug!("TypeWellFormedFromEnv is only used for Chalk") } - ty::PredicateKind::AliasEq(..) => { - bug!("We should only wf check where clauses and `AliasEq` is not a `Clause`") + ty::PredicateKind::AliasRelate(..) => { + bug!("We should only wf check where clauses and `AliasRelate` is not a `Clause`") } } @@ -936,7 +936,7 @@ pub(crate) fn required_region_bounds<'tcx>( | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) | ty::PredicateKind::Ambiguous - | ty::PredicateKind::AliasEq(..) + | ty::PredicateKind::AliasRelate(..) | ty::PredicateKind::TypeWellFormedFromEnv(..) => None, ty::PredicateKind::Clause(ty::Clause::TypeOutlives(ty::OutlivesPredicate( ref t, diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs index 60e22d1001c81..0e9bccba8d4c5 100644 --- a/compiler/rustc_traits/src/chalk/lowering.rs +++ b/compiler/rustc_traits/src/chalk/lowering.rs @@ -119,7 +119,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::InEnvironment LowerInto<'tcx, chalk_ir::GoalData>> for ty::Predi // some of these in terms of chalk operations. ty::PredicateKind::ClosureKind(..) | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) - | ty::PredicateKind::AliasEq(..) + | ty::PredicateKind::AliasRelate(..) | ty::PredicateKind::Coerce(..) | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::Ambiguous @@ -652,7 +652,7 @@ impl<'tcx> LowerInto<'tcx, Option None, ty::PredicateKind::ObjectSafe(..) - | ty::PredicateKind::AliasEq(..) + | ty::PredicateKind::AliasRelate(..) | ty::PredicateKind::ClosureKind(..) | ty::PredicateKind::Subtype(..) | ty::PredicateKind::Coerce(..) @@ -787,7 +787,7 @@ impl<'tcx> LowerInto<'tcx, Option None, ty::PredicateKind::Clause(ty::Clause::RegionOutlives(..)) - | ty::PredicateKind::AliasEq(..) + | ty::PredicateKind::AliasRelate(..) | ty::PredicateKind::ObjectSafe(..) | ty::PredicateKind::ClosureKind(..) | ty::PredicateKind::Subtype(..) diff --git a/compiler/rustc_traits/src/implied_outlives_bounds.rs b/compiler/rustc_traits/src/implied_outlives_bounds.rs index ddd4ca1436c09..f5bba14d2fb9c 100644 --- a/compiler/rustc_traits/src/implied_outlives_bounds.rs +++ b/compiler/rustc_traits/src/implied_outlives_bounds.rs @@ -86,7 +86,7 @@ fn compute_implied_outlives_bounds<'tcx>( if obligation.predicate.has_non_region_infer() { match obligation.predicate.kind().skip_binder() { ty::PredicateKind::Clause(ty::Clause::Projection(..)) - | ty::PredicateKind::AliasEq(..) => { + | ty::PredicateKind::AliasRelate(..) => { ocx.register_obligation(obligation.clone()); } _ => {} @@ -110,7 +110,7 @@ fn compute_implied_outlives_bounds<'tcx>( | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) | ty::PredicateKind::Ambiguous - | ty::PredicateKind::AliasEq(..) + | ty::PredicateKind::AliasRelate(..) | ty::PredicateKind::TypeWellFormedFromEnv(..) => {} // We need to search through *all* WellFormed predicates diff --git a/compiler/rustc_traits/src/normalize_erasing_regions.rs b/compiler/rustc_traits/src/normalize_erasing_regions.rs index f0597f19225c8..126a494f34fd6 100644 --- a/compiler/rustc_traits/src/normalize_erasing_regions.rs +++ b/compiler/rustc_traits/src/normalize_erasing_regions.rs @@ -61,7 +61,7 @@ fn not_outlives_predicate(p: ty::Predicate<'_>) -> bool { ty::PredicateKind::Clause(ty::Clause::Trait(..)) | ty::PredicateKind::Clause(ty::Clause::Projection(..)) | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) - | ty::PredicateKind::AliasEq(..) + | ty::PredicateKind::AliasRelate(..) | ty::PredicateKind::WellFormed(..) | ty::PredicateKind::ObjectSafe(..) | ty::PredicateKind::ClosureKind(..) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index e3e5454ef5443..44dfff0efbe94 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -324,7 +324,7 @@ pub(crate) fn clean_predicate<'tcx>( ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) => None, ty::PredicateKind::Subtype(..) - | ty::PredicateKind::AliasEq(..) + | ty::PredicateKind::AliasRelate(..) | ty::PredicateKind::Coerce(..) | ty::PredicateKind::ObjectSafe(..) | ty::PredicateKind::ClosureKind(..) diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index 24403e8b6f347..58f7742ab8764 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -37,7 +37,7 @@ pub fn is_min_const_fn<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, msrv: &Msrv) | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) | ty::PredicateKind::TypeWellFormedFromEnv(..) => continue, - ty::PredicateKind::AliasEq(..) => panic!("alias eq predicate on function: {predicate:#?}"), + ty::PredicateKind::AliasRelate(..) => panic!("alias relate predicate on function: {predicate:#?}"), ty::PredicateKind::ObjectSafe(_) => panic!("object safe predicate on function: {predicate:#?}"), ty::PredicateKind::ClosureKind(..) => panic!("closure kind predicate on function: {predicate:#?}"), ty::PredicateKind::Subtype(_) => panic!("subtype predicate on function: {predicate:#?}"), From f6fd7546804dd25d4996196dbc9653bde2b4a131 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 21 Mar 2023 22:20:54 +0000 Subject: [PATCH 14/16] Printing alias-relate goals correctly --- compiler/rustc_middle/src/ty/mod.rs | 10 ++++++++++ compiler/rustc_middle/src/ty/print/pretty.rs | 3 +-- compiler/rustc_middle/src/ty/structural_impls.rs | 5 +++-- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 4ab3df917e34c..23139e6be7abe 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -661,6 +661,16 @@ impl AliasRelationDirection { } } +impl std::fmt::Display for AliasRelationDirection { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + AliasRelationDirection::Equate => write!(f, " == "), + AliasRelationDirection::Subtype => write!(f, " <: "), + AliasRelationDirection::Supertype => write!(f, " :> "), + } + } +} + /// The crate outlives map is computed during typeck and contains the /// outlives of every item in the local crate. You should not use it /// directly, because to do so will make your pass dependent on the diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index ad5c9d93b4704..e9f8f2e586592 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -2847,8 +2847,7 @@ define_print_and_forward_display! { p!("the type `", print(ty), "` is found in the environment") } ty::PredicateKind::Ambiguous => p!("ambiguous"), - // TODO - ty::PredicateKind::AliasRelate(t1, t2, _) => p!(print(t1), " == ", print(t2)), + ty::PredicateKind::AliasRelate(t1, t2, dir) => p!(print(t1), write(" {} ", dir), print(t2)), } } diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index ad5f33d34dc2c..c6bb814679586 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -177,8 +177,9 @@ impl<'tcx> fmt::Debug for ty::PredicateKind<'tcx> { write!(f, "TypeWellFormedFromEnv({:?})", ty) } ty::PredicateKind::Ambiguous => write!(f, "Ambiguous"), - // TODO - ty::PredicateKind::AliasRelate(t1, t2, _) => write!(f, "AliasRelate({t1:?}, {t2:?})"), + ty::PredicateKind::AliasRelate(t1, t2, dir) => { + write!(f, "AliasRelate({t1:?}, {dir:?}, {t2:?})") + } } } } From 244cdaa457d80b3e1ef90795a48833f948ac0db9 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 22 Mar 2023 16:58:51 +0000 Subject: [PATCH 15/16] Remove AliasRelationDirection::Supertype --- compiler/rustc_infer/src/infer/combine.rs | 12 +- .../rustc_infer/src/infer/nll_relate/mod.rs | 30 ++++- compiler/rustc_middle/src/ty/mod.rs | 12 -- .../src/solve/eval_ctxt.rs | 19 +++ .../rustc_trait_selection/src/solve/mod.rs | 117 ++++++++---------- 5 files changed, 99 insertions(+), 91 deletions(-) diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs index 3fadc243dcd7a..88a28e26005d6 100644 --- a/compiler/rustc_infer/src/infer/combine.rs +++ b/compiler/rustc_infer/src/infer/combine.rs @@ -128,7 +128,7 @@ impl<'tcx> InferCtxt<'tcx> { (_, ty::Alias(AliasKind::Projection, _)) | (ty::Alias(AliasKind::Projection, _), _) if self.tcx.trait_solver_next() => { - relation.register_type_equate_obligation(a, b); + relation.register_type_relate_obligation(a, b); Ok(a) } @@ -848,10 +848,9 @@ pub trait ObligationEmittingRelation<'tcx>: TypeRelation<'tcx> { })]); } - /// Register an obligation that both types must be equal to each other. - /// - /// If they aren't equal then the relation doesn't hold. - fn register_type_equate_obligation(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) { + /// Register an obligation that both types must be related to each other according to + /// the [`ty::AliasRelationDirection`] given by [`ObligationEmittingRelation::alias_relate_direction`] + fn register_type_relate_obligation(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) { self.register_predicates([ty::Binder::dummy(ty::PredicateKind::AliasRelate( a.into(), b.into(), @@ -859,7 +858,8 @@ pub trait ObligationEmittingRelation<'tcx>: TypeRelation<'tcx> { ))]); } - /// Relation direction emitted for `AliasRelate` predicates + /// Relation direction emitted for `AliasRelate` predicates, corresponding to the direction + /// of the relation. fn alias_relate_direction(&self) -> ty::AliasRelationDirection; } diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs index 216d2965da761..61d1b69be5581 100644 --- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs +++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs @@ -779,13 +779,31 @@ where } fn alias_relate_direction(&self) -> ty::AliasRelationDirection { - match self.ambient_variance { - ty::Variance::Covariant => ty::AliasRelationDirection::Subtype, - ty::Variance::Contravariant => ty::AliasRelationDirection::Supertype, - ty::Variance::Invariant => ty::AliasRelationDirection::Equate, - // FIXME(deferred_projection_equality): Implement this when we trigger it + unreachable!("manually overridden to handle ty::Variance::Contravariant ambient variance") + } + + fn register_type_relate_obligation(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) { + self.register_predicates([ty::Binder::dummy(match self.ambient_variance { + ty::Variance::Covariant => ty::PredicateKind::AliasRelate( + a.into(), + b.into(), + ty::AliasRelationDirection::Subtype, + ), + // a :> b is b <: a + ty::Variance::Contravariant => ty::PredicateKind::AliasRelate( + b.into(), + a.into(), + ty::AliasRelationDirection::Subtype, + ), + ty::Variance::Invariant => ty::PredicateKind::AliasRelate( + a.into(), + b.into(), + ty::AliasRelationDirection::Equate, + ), + // FIXME(deferred_projection_equality): Implement this when we trigger it. + // Probably just need to do nothing here. ty::Variance::Bivariant => unreachable!(), - } + })]); } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 23139e6be7abe..7ea242f55b0f1 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -648,17 +648,6 @@ pub enum PredicateKind<'tcx> { pub enum AliasRelationDirection { Equate, Subtype, - Supertype, -} - -impl AliasRelationDirection { - pub fn invert(self) -> Self { - match self { - AliasRelationDirection::Equate => AliasRelationDirection::Equate, - AliasRelationDirection::Subtype => AliasRelationDirection::Supertype, - AliasRelationDirection::Supertype => AliasRelationDirection::Subtype, - } - } } impl std::fmt::Display for AliasRelationDirection { @@ -666,7 +655,6 @@ impl std::fmt::Display for AliasRelationDirection { match self { AliasRelationDirection::Equate => write!(f, " == "), AliasRelationDirection::Subtype => write!(f, " <: "), - AliasRelationDirection::Supertype => write!(f, " :> "), } } } diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs index 4cfea28475732..75b304cce4e09 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs @@ -459,6 +459,25 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { }) } + #[instrument(level = "debug", skip(self, param_env), ret)] + pub(super) fn sub>( + &mut self, + param_env: ty::ParamEnv<'tcx>, + sub: T, + sup: T, + ) -> Result<(), NoSolution> { + self.infcx + .at(&ObligationCause::dummy(), param_env) + .sub(DefineOpaqueTypes::No, sub, sup) + .map(|InferOk { value: (), obligations }| { + self.add_goals(obligations.into_iter().map(|o| o.into())); + }) + .map_err(|e| { + debug!(?e, "failed to subtype"); + NoSolution + }) + } + /// Equates two values returning the nested goals without adding them /// to the nested goals of the `EvalCtxt`. /// diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index 5cda9da3c5a31..4c87d36ca0dc1 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -17,7 +17,6 @@ use rustc_hir::def_id::DefId; use rustc_infer::infer::canonical::{Canonical, CanonicalVarValues}; -use rustc_infer::infer::{DefineOpaqueTypes, InferOk}; use rustc_infer::traits::query::NoSolution; use rustc_middle::traits::solve::{ CanonicalGoal, CanonicalResponse, Certainty, ExternalConstraints, ExternalConstraintsData, @@ -101,11 +100,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { // That won't actually reflect in the query response, so it seems moot. self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) } else { - let InferOk { value: (), obligations } = self - .infcx - .at(&ObligationCause::dummy(), goal.param_env) - .sub(DefineOpaqueTypes::No, goal.predicate.a, goal.predicate.b)?; - self.add_goals(obligations.into_iter().map(|pred| pred.into())); + self.sub(goal.param_env, goal.predicate.a, goal.predicate.b)?; self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } } @@ -161,44 +156,41 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { goal: Goal<'tcx, (ty::Term<'tcx>, ty::Term<'tcx>, ty::AliasRelationDirection)>, ) -> QueryResult<'tcx> { let tcx = self.tcx(); - - let evaluate_normalizes_to = |ecx: &mut EvalCtxt<'_, 'tcx>, alias, other, direction| { - debug!("evaluate_normalizes_to(alias={:?}, other={:?})", alias, other); - let result = ecx.probe(|ecx| { - let other = match direction { - // This is purely an optimization. - ty::AliasRelationDirection::Equate => other, - - ty::AliasRelationDirection::Subtype | ty::AliasRelationDirection::Supertype => { - let fresh = ecx.next_term_infer_of_kind(other); - let (sub, sup) = if direction == ty::AliasRelationDirection::Subtype { - (fresh, other) - } else { - (other, fresh) - }; - ecx.add_goals( - ecx.infcx - .at(&ObligationCause::dummy(), goal.param_env) - .sub(DefineOpaqueTypes::No, sub, sup)? - .into_obligations() - .into_iter() - .map(|o| o.into()), - ); - fresh - } - }; - ecx.add_goal(goal.with( - tcx, - ty::Binder::dummy(ty::ProjectionPredicate { - projection_ty: alias, - term: other, - }), - )); - ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) - }); - debug!("evaluate_normalizes_to({alias}, {other}, {direction:?}) -> {result:?}"); - result - }; + // We may need to invert the alias relation direction if dealing an alias on the RHS. + enum Invert { + No, + Yes, + } + let evaluate_normalizes_to = + |ecx: &mut EvalCtxt<'_, 'tcx>, alias, other, direction, invert| { + debug!("evaluate_normalizes_to(alias={:?}, other={:?})", alias, other); + let result = ecx.probe(|ecx| { + let other = match direction { + // This is purely an optimization. + ty::AliasRelationDirection::Equate => other, + + ty::AliasRelationDirection::Subtype => { + let fresh = ecx.next_term_infer_of_kind(other); + let (sub, sup) = match invert { + Invert::No => (fresh, other), + Invert::Yes => (other, fresh), + }; + ecx.sub(goal.param_env, sub, sup)?; + fresh + } + }; + ecx.add_goal(goal.with( + tcx, + ty::Binder::dummy(ty::ProjectionPredicate { + projection_ty: alias, + term: other, + }), + )); + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + }); + debug!("evaluate_normalizes_to({alias}, {other}, {direction:?}) -> {result:?}"); + result + }; let (lhs, rhs, direction) = goal.predicate; @@ -212,11 +204,13 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { (None, None) => bug!("`AliasRelate` goal without an alias on either lhs or rhs"), // RHS is not a projection, only way this is true is if LHS normalizes-to RHS - (Some(alias_lhs), None) => evaluate_normalizes_to(self, alias_lhs, rhs, direction), + (Some(alias_lhs), None) => { + evaluate_normalizes_to(self, alias_lhs, rhs, direction, Invert::No) + } // LHS is not a projection, only way this is true is if RHS normalizes-to LHS (None, Some(alias_rhs)) => { - evaluate_normalizes_to(self, alias_rhs, lhs, direction.invert()) + evaluate_normalizes_to(self, alias_rhs, lhs, direction, Invert::Yes) } (Some(alias_lhs), Some(alias_rhs)) => { @@ -224,34 +218,23 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { let candidates = vec![ // LHS normalizes-to RHS - evaluate_normalizes_to(self, alias_lhs, rhs, direction), + evaluate_normalizes_to(self, alias_lhs, rhs, direction, Invert::No), // RHS normalizes-to RHS - evaluate_normalizes_to(self, alias_rhs, lhs, direction.invert()), + evaluate_normalizes_to(self, alias_rhs, lhs, direction, Invert::Yes), // Relate via substs self.probe(|ecx| { debug!( "compute_alias_relate_goal: alias defids are equal, equating substs" ); - ecx.add_goals( - match direction { - ty::AliasRelationDirection::Equate => ecx - .infcx - .at(&ObligationCause::dummy(), goal.param_env) - .eq(DefineOpaqueTypes::No, alias_lhs, alias_rhs), - ty::AliasRelationDirection::Subtype => ecx - .infcx - .at(&ObligationCause::dummy(), goal.param_env) - .sub(DefineOpaqueTypes::No, alias_lhs, alias_rhs), - ty::AliasRelationDirection::Supertype => ecx - .infcx - .at(&ObligationCause::dummy(), goal.param_env) - .sup(DefineOpaqueTypes::No, alias_lhs, alias_rhs), - }? - .into_obligations() - .into_iter() - .map(|o| o.into()), - ); + match direction { + ty::AliasRelationDirection::Equate => { + ecx.eq(goal.param_env, alias_lhs, alias_rhs)?; + } + ty::AliasRelationDirection::Subtype => { + ecx.sub(goal.param_env, alias_lhs, alias_rhs)?; + } + } ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }), From e5189cc7e45991e1c6e9a4218c80d54441b346a9 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 27 Feb 2023 20:47:06 +0000 Subject: [PATCH 16/16] Nested impl traits trigger opaque_hidden_inferred_bound too much --- .../src/opaque_hidden_inferred_bound.rs | 21 ++++++++++++++++--- tests/ui/impl-trait/nested-return-type2.rs | 1 - .../ui/impl-trait/nested-return-type2.stderr | 17 --------------- tests/ui/impl-trait/nested-return-type3.rs | 1 - .../ui/impl-trait/nested-return-type3.stderr | 17 --------------- 5 files changed, 18 insertions(+), 39 deletions(-) delete mode 100644 tests/ui/impl-trait/nested-return-type2.stderr delete mode 100644 tests/ui/impl-trait/nested-return-type3.stderr diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs index 883a56cb3ce6b..f9d43fe220036 100644 --- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs +++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs @@ -27,6 +27,8 @@ declare_lint! { /// ### Example /// /// ```rust + /// #![feature(type_alias_impl_trait)] + /// /// trait Duh {} /// /// impl Duh for i32 {} @@ -41,7 +43,9 @@ declare_lint! { /// type Assoc = F; /// } /// - /// fn test() -> impl Trait { + /// type Tait = impl Sized; + /// + /// fn test() -> impl Trait { /// 42 /// } /// ``` @@ -54,7 +58,7 @@ declare_lint! { /// /// Although the hidden type, `i32` does satisfy this bound, we do not /// consider the return type to be well-formed with this lint. It can be - /// fixed by changing `impl Sized` into `impl Sized + Send`. + /// fixed by changing `Tait = impl Sized` into `Tait = impl Sized + Send`. pub OPAQUE_HIDDEN_INFERRED_BOUND, Warn, "detects the use of nested `impl Trait` types in associated type bounds that are not general enough" @@ -64,7 +68,7 @@ declare_lint_pass!(OpaqueHiddenInferredBound => [OPAQUE_HIDDEN_INFERRED_BOUND]); impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) { - let hir::ItemKind::OpaqueTy(_) = &item.kind else { return; }; + let hir::ItemKind::OpaqueTy(opaque) = &item.kind else { return; }; let def_id = item.owner_id.def_id.to_def_id(); let infcx = &cx.tcx.infer_ctxt().build(); // For every projection predicate in the opaque type's explicit bounds, @@ -81,6 +85,17 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound { // have opaques in them anyways. let Some(proj_term) = proj.term.ty() else { continue }; + // HACK: `impl Trait` from an RPIT is "ok"... + if let ty::Alias(ty::Opaque, opaque_ty) = *proj_term.kind() + && cx.tcx.parent(opaque_ty.def_id) == def_id + && matches!( + opaque.origin, + hir::OpaqueTyOrigin::FnReturn(_) | hir::OpaqueTyOrigin::AsyncFn(_) + ) + { + continue; + } + let proj_ty = cx.tcx.mk_projection(proj.projection_ty.def_id, proj.projection_ty.substs); // For every instance of the projection type in the bounds, diff --git a/tests/ui/impl-trait/nested-return-type2.rs b/tests/ui/impl-trait/nested-return-type2.rs index fe883ce6fc8ed..e1d5511379e7a 100644 --- a/tests/ui/impl-trait/nested-return-type2.rs +++ b/tests/ui/impl-trait/nested-return-type2.rs @@ -26,7 +26,6 @@ impl R> Trait for F { // Lazy TAIT would error out, but we inserted a hack to make it work again, // keeping backwards compatibility. fn foo() -> impl Trait { - //~^ WARN opaque type `impl Trait` does not satisfy its associated type bounds || 42 } diff --git a/tests/ui/impl-trait/nested-return-type2.stderr b/tests/ui/impl-trait/nested-return-type2.stderr deleted file mode 100644 index 09ad3bd05c1b3..0000000000000 --- a/tests/ui/impl-trait/nested-return-type2.stderr +++ /dev/null @@ -1,17 +0,0 @@ -warning: opaque type `impl Trait` does not satisfy its associated type bounds - --> $DIR/nested-return-type2.rs:28:24 - | -LL | type Assoc: Duh; - | --- this associated type bound is unsatisfied for `impl Send` -... -LL | fn foo() -> impl Trait { - | ^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(opaque_hidden_inferred_bound)]` on by default -help: add this bound - | -LL | fn foo() -> impl Trait { - | +++++ - -warning: 1 warning emitted - diff --git a/tests/ui/impl-trait/nested-return-type3.rs b/tests/ui/impl-trait/nested-return-type3.rs index 5a764fc4c285a..74b4dae22ebfd 100644 --- a/tests/ui/impl-trait/nested-return-type3.rs +++ b/tests/ui/impl-trait/nested-return-type3.rs @@ -13,7 +13,6 @@ impl Trait for F { } fn foo() -> impl Trait { - //~^ WARN opaque type `impl Trait` does not satisfy its associated type bounds 42 } diff --git a/tests/ui/impl-trait/nested-return-type3.stderr b/tests/ui/impl-trait/nested-return-type3.stderr deleted file mode 100644 index 632de71aa4c88..0000000000000 --- a/tests/ui/impl-trait/nested-return-type3.stderr +++ /dev/null @@ -1,17 +0,0 @@ -warning: opaque type `impl Trait` does not satisfy its associated type bounds - --> $DIR/nested-return-type3.rs:15:24 - | -LL | type Assoc: Duh; - | --- this associated type bound is unsatisfied for `impl Send` -... -LL | fn foo() -> impl Trait { - | ^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(opaque_hidden_inferred_bound)]` on by default -help: add this bound - | -LL | fn foo() -> impl Trait { - | +++++ - -warning: 1 warning emitted -