diff options
| author | bors <bors@rust-lang.org> | 2023-03-14 00:30:46 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2023-03-14 00:30:46 +0000 |
| commit | c54af457d05722321ca88c2ae0e5706ef803c5fb (patch) | |
| tree | 04c6c57d4f325d76ae7de556262bf908fbaf70df /compiler | |
| parent | 22f247c6f3ed388cb702d01c2ff27da658a8b353 (diff) | |
| parent | 30cd4b3a161d38574a599f2aa58db8334b470f8b (diff) | |
| download | rust-c54af457d05722321ca88c2ae0e5706ef803c5fb.tar.gz rust-c54af457d05722321ca88c2ae0e5706ef803c5fb.zip | |
Auto merge of #109097 - matthiaskrgr:rollup-6ydc4ri, r=matthiaskrgr
Rollup of 9 pull requests Successful merges: - #108419 (Stabilize `atomic_as_ptr`) - #108507 (use `as_ptr` to determine the address of atomics) - #108607 (Don't use fd-lock on Solaris in bootstrap) - #108830 (Treat projections with infer as placeholder during fast reject in new solver) - #109055 (create `config::tests::detect_src_and_out` test for bootstrap) - #109058 (Document BinOp::is_checkable) - #109081 (simd-wide-sum test: adapt for LLVM 17 codegen change) - #109083 (Update books) - #109088 (Gracefully handle `#[target_feature]` on statics) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
Diffstat (limited to 'compiler')
18 files changed, 209 insertions, 101 deletions
diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 8b6bf886b0d..f9bb8359208 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -61,25 +61,29 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs { let supported_target_features = tcx.supported_target_features(LOCAL_CRATE); - // In some cases, attribute are only valid on functions, but it's the `check_attr` - // pass that check that they aren't used anywhere else, rather this module. - // In these cases, we bail from performing further checks that are only meaningful for - // functions (such as calling `fn_sig`, which ICEs if given a non-function). We also - // report a delayed bug, just in case `check_attr` isn't doing its job. - let validate_fn_only_attr = |attr_sp| -> bool { - let def_kind = tcx.def_kind(did); - if let DefKind::Fn | DefKind::AssocFn | DefKind::Variant | DefKind::Ctor(..) = def_kind { - true - } else { - tcx.sess.delay_span_bug(attr_sp, "this attribute can only be applied to functions"); - false - } - }; - let mut inline_span = None; let mut link_ordinal_span = None; let mut no_sanitize_span = None; + for attr in attrs.iter() { + // In some cases, attribute are only valid on functions, but it's the `check_attr` + // pass that check that they aren't used anywhere else, rather this module. + // In these cases, we bail from performing further checks that are only meaningful for + // functions (such as calling `fn_sig`, which ICEs if given a non-function). We also + // report a delayed bug, just in case `check_attr` isn't doing its job. + let fn_sig = || { + use DefKind::*; + + let def_kind = tcx.def_kind(did); + if let Fn | AssocFn | Variant | Ctor(..) = def_kind { + Some(tcx.fn_sig(did)) + } else { + tcx.sess + .delay_span_bug(attr.span, "this attribute can only be applied to functions"); + None + } + }; + if attr.has_name(sym::cold) { codegen_fn_attrs.flags |= CodegenFnAttrFlags::COLD; } else if attr.has_name(sym::rustc_allocator) { @@ -169,8 +173,8 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs { } } } else if attr.has_name(sym::cmse_nonsecure_entry) { - if validate_fn_only_attr(attr.span) - && !matches!(tcx.fn_sig(did).skip_binder().abi(), abi::Abi::C { .. }) + if let Some(fn_sig) = fn_sig() + && !matches!(fn_sig.skip_binder().abi(), abi::Abi::C { .. }) { struct_span_err!( tcx.sess, @@ -189,8 +193,8 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs { codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL; } else if attr.has_name(sym::track_caller) { if !tcx.is_closure(did.to_def_id()) - && validate_fn_only_attr(attr.span) - && tcx.fn_sig(did).skip_binder().abi() != abi::Abi::Rust + && let Some(fn_sig) = fn_sig() + && fn_sig.skip_binder().abi() != abi::Abi::Rust { struct_span_err!(tcx.sess, attr.span, E0737, "`#[track_caller]` requires Rust ABI") .emit(); @@ -222,7 +226,8 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs { } } else if attr.has_name(sym::target_feature) { if !tcx.is_closure(did.to_def_id()) - && tcx.fn_sig(did).skip_binder().unsafety() == hir::Unsafety::Normal + && let Some(fn_sig) = fn_sig() + && fn_sig.skip_binder().unsafety() == hir::Unsafety::Normal { if tcx.sess.target.is_like_wasm || tcx.sess.opts.actually_rustdoc { // The `#[target_feature]` attribute is allowed on diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs index 02f3eeee0e7..07a33bcbb50 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs @@ -11,7 +11,7 @@ use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId}; -use rustc_middle::ty::fast_reject::{simplify_type, SimplifiedType, TreatParams}; +use rustc_middle::ty::fast_reject::{simplify_type, SimplifiedType, TreatParams, TreatProjections}; use rustc_middle::ty::{self, CrateInherentImpls, Ty, TyCtxt}; use rustc_span::symbol::sym; @@ -99,7 +99,12 @@ impl<'tcx> InherentCollect<'tcx> { } } - if let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::AsInfer) { + if let Some(simp) = simplify_type( + self.tcx, + self_ty, + TreatParams::AsCandidateKey, + TreatProjections::AsCandidateKey, + ) { self.impls_map.incoherent_impls.entry(simp).or_default().push(impl_def_id); } else { bug!("unexpected self type: {:?}", self_ty); @@ -159,7 +164,12 @@ impl<'tcx> InherentCollect<'tcx> { } } - if let Some(simp) = simplify_type(self.tcx, ty, TreatParams::AsInfer) { + if let Some(simp) = simplify_type( + self.tcx, + ty, + TreatParams::AsCandidateKey, + TreatProjections::AsCandidateKey, + ) { self.impls_map.incoherent_impls.entry(simp).or_default().push(impl_def_id); } else { bug!("unexpected primitive type: {:?}", ty); diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 57805f7c800..562dd2caae3 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -15,6 +15,7 @@ use rustc_infer::infer::canonical::OriginalQueryValues; use rustc_infer::infer::canonical::{Canonical, QueryResponse}; use rustc_infer::infer::{self, InferOk, TyCtxtInferExt}; use rustc_middle::middle::stability; +use rustc_middle::ty::fast_reject::TreatProjections; use rustc_middle::ty::fast_reject::{simplify_type, TreatParams}; use rustc_middle::ty::AssocItem; use rustc_middle::ty::GenericParamDefKind; @@ -699,7 +700,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } fn assemble_inherent_candidates_for_incoherent_ty(&mut self, self_ty: Ty<'tcx>) { - let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::AsInfer) else { + let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::AsCandidateKey, TreatProjections::AsCandidateKey) else { bug!("unexpected incoherent type: {:?}", self_ty) }; for &impl_def_id in self.tcx.incoherent_impls(simp) { diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 4b15e48bd27..7055d9257ec 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -25,6 +25,7 @@ use rustc_infer::infer::{ use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; use rustc_middle::traits::util::supertraits; use rustc_middle::ty::fast_reject::DeepRejectCtxt; +use rustc_middle::ty::fast_reject::TreatProjections; use rustc_middle::ty::fast_reject::{simplify_type, TreatParams}; use rustc_middle::ty::print::{with_crate_prefix, with_forced_trimmed_paths}; use rustc_middle::ty::{self, GenericArgKind, Ty, TyCtxt, TypeVisitableExt}; @@ -1257,7 +1258,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let target_ty = self .autoderef(sugg_span, rcvr_ty) .find(|(rcvr_ty, _)| { - DeepRejectCtxt { treat_obligation_params: TreatParams::AsInfer } + DeepRejectCtxt { treat_obligation_params: TreatParams::AsCandidateKey } .types_may_unify(*rcvr_ty, impl_ty) }) .map_or(impl_ty, |(ty, _)| ty) @@ -1516,7 +1517,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .into_iter() .any(|info| self.associated_value(info.def_id, item_name).is_some()); let found_assoc = |ty: Ty<'tcx>| { - simplify_type(tcx, ty, TreatParams::AsInfer) + simplify_type(tcx, ty, TreatParams::AsCandidateKey, TreatProjections::AsCandidateKey) .and_then(|simp| { tcx.incoherent_impls(simp) .iter() @@ -2645,9 +2646,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // FIXME: Even though negative bounds are not implemented, we could maybe handle // cases where a positive bound implies a negative impl. (candidates, Vec::new()) - } else if let Some(simp_rcvr_ty) = - simplify_type(self.tcx, rcvr_ty, TreatParams::AsPlaceholder) - { + } else if let Some(simp_rcvr_ty) = simplify_type( + self.tcx, + rcvr_ty, + TreatParams::ForLookup, + TreatProjections::ForLookup, + ) { let mut potential_candidates = Vec::new(); let mut explicitly_negative = Vec::new(); for candidate in candidates { @@ -2660,8 +2664,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }) .any(|imp_did| { let imp = self.tcx.impl_trait_ref(imp_did).unwrap().subst_identity(); - let imp_simp = - simplify_type(self.tcx, imp.self_ty(), TreatParams::AsPlaceholder); + let imp_simp = simplify_type( + self.tcx, + imp.self_ty(), + TreatParams::ForLookup, + TreatProjections::ForLookup, + ); imp_simp.map_or(false, |s| s == simp_rcvr_ty) }) { diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 16306bef42e..bbab8a62a2b 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -26,7 +26,7 @@ use rustc_middle::middle::exported_symbols::{ use rustc_middle::mir::interpret; use rustc_middle::traits::specialization_graph; use rustc_middle::ty::codec::TyEncoder; -use rustc_middle::ty::fast_reject::{self, SimplifiedType, TreatParams}; +use rustc_middle::ty::fast_reject::{self, SimplifiedType, TreatParams, TreatProjections}; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, SymbolName, Ty, TyCtxt}; use rustc_middle::util::common::to_readable_str; @@ -1858,7 +1858,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let simplified_self_ty = fast_reject::simplify_type( self.tcx, trait_ref.self_ty(), - TreatParams::AsInfer, + TreatParams::AsCandidateKey, + TreatProjections::AsCandidateKey, ); fx_hash_map diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 5215e3db798..b34651c3ea7 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -1999,6 +1999,9 @@ impl BorrowKind { } impl BinOp { + /// The checkable operators are those whose overflow checking behavior is controlled by + /// -Coverflow-checks option. The remaining operators have either no overflow conditions (e.g., + /// BitAnd, BitOr, BitXor) or are always checked for overflow (e.g., Div, Rem). pub fn is_checkable(self) -> bool { use self::BinOp::*; matches!(self, Add | Sub | Mul | Shl | Shr) diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs index 59deade0a07..ee505742be9 100644 --- a/compiler/rustc_middle/src/ty/fast_reject.rs +++ b/compiler/rustc_middle/src/ty/fast_reject.rs @@ -51,15 +51,35 @@ pub enum SimplifiedType { /// generic parameters as if they were inference variables in that case. #[derive(PartialEq, Eq, Debug, Clone, Copy)] pub enum TreatParams { - /// Treat parameters as placeholders in the given environment. + /// Treat parameters as infer vars. This is the correct mode for caching + /// an impl's type for lookup. + AsCandidateKey, + /// Treat parameters as placeholders in the given environment. This is the + /// correct mode for *lookup*, as during candidate selection. + ForLookup, +} + +/// During fast-rejection, we have the choice of treating projection types +/// as either simplifyable or not, depending on whether we expect the projection +/// to be normalized/rigid. +#[derive(PartialEq, Eq, Debug, Clone, Copy)] +pub enum TreatProjections { + /// In candidates, we may be able to normalize the projection + /// after instantiating the candidate and equating it with a goal. /// - /// Note that this also causes us to treat projections as if they were - /// placeholders. This is only correct if the given projection cannot - /// be normalized in the current context. Even if normalization fails, - /// it may still succeed later if the projection contains any inference - /// variables. - AsPlaceholder, - AsInfer, + /// We must assume that the `impl<T> Trait<T> for <T as Id>::This` + /// can apply to all self types so we don't return a simplified type + /// for `<T as Id>::This`. + AsCandidateKey, + /// In the old solver we don't try to normalize projections + /// when looking up impls and only access them by using the + /// current self type. This means that if the self type is + /// a projection which could later be normalized, we must not + /// treat it as rigid. + ForLookup, + /// We can treat projections in the self type as opaque as + /// we separately look up impls for the normalized self type. + NextSolverLookup, } /// Tries to simplify a type by only returning the outermost injective¹ layer, if one exists. @@ -87,6 +107,7 @@ pub fn simplify_type<'tcx>( tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, treat_params: TreatParams, + treat_projections: TreatProjections, ) -> Option<SimplifiedType> { match *ty.kind() { ty::Bool => Some(BoolSimplifiedType), @@ -115,19 +136,13 @@ pub fn simplify_type<'tcx>( ty::FnPtr(f) => Some(FunctionSimplifiedType(f.skip_binder().inputs().len())), ty::Placeholder(..) => Some(PlaceholderSimplifiedType), ty::Param(_) => match treat_params { - TreatParams::AsPlaceholder => Some(PlaceholderSimplifiedType), - TreatParams::AsInfer => None, + TreatParams::ForLookup => Some(PlaceholderSimplifiedType), + TreatParams::AsCandidateKey => None, }, - ty::Alias(..) => match treat_params { - // When treating `ty::Param` as a placeholder, projections also - // don't unify with anything else as long as they are fully normalized. - // - // We will have to be careful with lazy normalization here. - TreatParams::AsPlaceholder if !ty.has_non_region_infer() => { - debug!("treating `{}` as a placeholder", ty); - Some(PlaceholderSimplifiedType) - } - TreatParams::AsPlaceholder | TreatParams::AsInfer => None, + ty::Alias(..) => match treat_projections { + TreatProjections::ForLookup if !ty.needs_infer() => Some(PlaceholderSimplifiedType), + TreatProjections::NextSolverLookup => Some(PlaceholderSimplifiedType), + TreatProjections::AsCandidateKey | TreatProjections::ForLookup => None, }, ty::Foreign(def_id) => Some(ForeignSimplifiedType(def_id)), ty::Bound(..) | ty::Infer(_) | ty::Error(_) => None, @@ -295,8 +310,8 @@ impl DeepRejectCtxt { // Depending on the value of `treat_obligation_params`, we either // treat generic parameters like placeholders or like inference variables. ty::Param(_) => match self.treat_obligation_params { - TreatParams::AsPlaceholder => false, - TreatParams::AsInfer => true, + TreatParams::ForLookup => false, + TreatParams::AsCandidateKey => true, }, ty::Infer(_) => true, @@ -333,8 +348,8 @@ impl DeepRejectCtxt { let k = impl_ct.kind(); match obligation_ct.kind() { ty::ConstKind::Param(_) => match self.treat_obligation_params { - TreatParams::AsPlaceholder => false, - TreatParams::AsInfer => true, + TreatParams::ForLookup => false, + TreatParams::AsCandidateKey => true, }, // As we don't necessarily eagerly evaluate constants, diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs index 649a58c9170..bf2b121f704 100644 --- a/compiler/rustc_middle/src/ty/trait_def.rs +++ b/compiler/rustc_middle/src/ty/trait_def.rs @@ -1,5 +1,5 @@ use crate::traits::specialization_graph; -use crate::ty::fast_reject::{self, SimplifiedType, TreatParams}; +use crate::ty::fast_reject::{self, SimplifiedType, TreatParams, TreatProjections}; use crate::ty::visit::TypeVisitableExt; use crate::ty::{Ident, Ty, TyCtxt}; use hir::def_id::LOCAL_CRATE; @@ -118,16 +118,32 @@ impl<'tcx> TyCtxt<'tcx> { /// Iterate over every impl that could possibly match the self type `self_ty`. /// /// `trait_def_id` MUST BE the `DefId` of a trait. - pub fn for_each_relevant_impl<F: FnMut(DefId)>( + pub fn for_each_relevant_impl( self, trait_def_id: DefId, self_ty: Ty<'tcx>, - mut f: F, + f: impl FnMut(DefId), ) { - let _: Option<()> = self.find_map_relevant_impl(trait_def_id, self_ty, |did| { - f(did); - None - }); + self.for_each_relevant_impl_treating_projections( + trait_def_id, + self_ty, + TreatProjections::ForLookup, + f, + ) + } + + pub fn for_each_relevant_impl_treating_projections( + self, + trait_def_id: DefId, + self_ty: Ty<'tcx>, + treat_projections: TreatProjections, + mut f: impl FnMut(DefId), + ) { + let _: Option<()> = + self.find_map_relevant_impl(trait_def_id, self_ty, treat_projections, |did| { + f(did); + None + }); } /// `trait_def_id` MUST BE the `DefId` of a trait. @@ -137,7 +153,12 @@ impl<'tcx> TyCtxt<'tcx> { self_ty: Ty<'tcx>, ) -> impl Iterator<Item = DefId> + 'tcx { let impls = self.trait_impls_of(trait_def_id); - if let Some(simp) = fast_reject::simplify_type(self, self_ty, TreatParams::AsInfer) { + if let Some(simp) = fast_reject::simplify_type( + self, + self_ty, + TreatParams::AsCandidateKey, + TreatProjections::AsCandidateKey, + ) { if let Some(impls) = impls.non_blanket_impls.get(&simp) { return impls.iter().copied(); } @@ -150,11 +171,12 @@ impl<'tcx> TyCtxt<'tcx> { /// the first non-none value. /// /// `trait_def_id` MUST BE the `DefId` of a trait. - pub fn find_map_relevant_impl<T, F: FnMut(DefId) -> Option<T>>( + pub fn find_map_relevant_impl<T>( self, trait_def_id: DefId, self_ty: Ty<'tcx>, - mut f: F, + treat_projections: TreatProjections, + mut f: impl FnMut(DefId) -> Option<T>, ) -> Option<T> { // FIXME: This depends on the set of all impls for the trait. That is // unfortunate wrt. incremental compilation. @@ -169,14 +191,13 @@ impl<'tcx> TyCtxt<'tcx> { } } - // Note that we're using `TreatParams::AsPlaceholder` to query `non_blanket_impls` while using - // `TreatParams::AsInfer` while actually adding them. - // // This way, when searching for some impl for `T: Trait`, we do not look at any impls // whose outer level is not a parameter or projection. Especially for things like // `T: Clone` this is incredibly useful as we would otherwise look at all the impls // of `Clone` for `Option<T>`, `Vec<T>`, `ConcreteType` and so on. - if let Some(simp) = fast_reject::simplify_type(self, self_ty, TreatParams::AsPlaceholder) { + if let Some(simp) = + fast_reject::simplify_type(self, self_ty, TreatParams::ForLookup, treat_projections) + { if let Some(impls) = impls.non_blanket_impls.get(&simp) { for &impl_def_id in impls { if let result @ Some(_) = f(impl_def_id) { @@ -237,9 +258,12 @@ pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> Trait continue; } - if let Some(simplified_self_ty) = - fast_reject::simplify_type(tcx, impl_self_ty, TreatParams::AsInfer) - { + if let Some(simplified_self_ty) = fast_reject::simplify_type( + tcx, + impl_self_ty, + TreatParams::AsCandidateKey, + TreatProjections::AsCandidateKey, + ) { impls.non_blanket_impls.entry(simplified_self_ty).or_default().push(impl_def_id); } else { impls.blanket_impls.push(impl_def_id); diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 8b5469743da..b0f6127baa5 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -2,6 +2,7 @@ use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; use crate::mir; +use crate::ty::fast_reject::TreatProjections; use crate::ty::layout::IntegerExt; use crate::ty::{ self, FallibleTypeFolder, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, @@ -363,14 +364,20 @@ impl<'tcx> TyCtxt<'tcx> { self.ensure().coherent_trait(drop_trait); let ty = self.type_of(adt_did).subst_identity(); - let (did, constness) = self.find_map_relevant_impl(drop_trait, ty, |impl_did| { - if let Some(item_id) = self.associated_item_def_ids(impl_did).first() { - if validate(self, impl_did).is_ok() { - return Some((*item_id, self.constness(impl_did))); + let (did, constness) = self.find_map_relevant_impl( + drop_trait, + ty, + // FIXME: This could also be some other mode, like "unexpected" + TreatProjections::ForLookup, + |impl_did| { + if let Some(item_id) = self.associated_item_def_ids(impl_did).first() { + if validate(self, impl_did).is_ok() { + return Some((*item_id, self.constness(impl_did))); + } } - } - None - })?; + None + }, + )?; Some(ty::Destructor { did, constness }) } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 5ef3e13eff8..c8d371dd084 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -2215,7 +2215,7 @@ impl CheckAttrVisitor<'_> { // `fn(TokenStream) -> TokenStream` after some substitution of generic arguments. // // Properly checking this means pulling in additional `rustc` crates, so we don't. - let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::AsInfer }; + let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::AsCandidateKey }; if sig.abi != Abi::Rust { tcx.sess.emit_err(errors::ProcMacroInvalidAbi { diff --git a/compiler/rustc_trait_selection/src/solve/assembly.rs b/compiler/rustc_trait_selection/src/solve/assembly.rs index 72b1b35e79b..891ea0cdebe 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly.rs @@ -8,6 +8,7 @@ use rustc_hir::def_id::DefId; use rustc_infer::traits::query::NoSolution; use rustc_infer::traits::util::elaborate_predicates; use rustc_middle::traits::solve::{CanonicalResponse, Certainty, Goal, MaybeCause, QueryResult}; +use rustc_middle::ty::fast_reject::TreatProjections; use rustc_middle::ty::TypeFoldable; use rustc_middle::ty::{self, Ty, TyCtxt}; use std::fmt::Debug; @@ -299,9 +300,10 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { candidates: &mut Vec<Candidate<'tcx>>, ) { let tcx = self.tcx(); - tcx.for_each_relevant_impl( + tcx.for_each_relevant_impl_treating_projections( goal.predicate.trait_def_id(tcx), goal.predicate.self_ty(), + TreatProjections::NextSolverLookup, |impl_def_id| match G::consider_impl_candidate(self, goal, impl_def_id) { Ok(result) => candidates .push(Candidate { source: CandidateSource::Impl(impl_def_id), result }), diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs index e206658b4b9..dbb8e722c8f 100644 --- a/compiler/rustc_trait_selection/src/solve/project_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs @@ -184,7 +184,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> { let goal_trait_ref = goal.predicate.projection_ty.trait_ref(tcx); let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap(); - let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::AsPlaceholder }; + let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::ForLookup }; if iter::zip(goal_trait_ref.substs, impl_trait_ref.skip_binder().substs) .any(|(goal, imp)| !drcx.generic_args_may_unify(goal, imp)) { diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index 0669975d638..7878539817c 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -8,7 +8,7 @@ use rustc_hir::LangItem; use rustc_infer::traits::query::NoSolution; use rustc_infer::traits::util::supertraits; use rustc_middle::traits::solve::{CanonicalResponse, Certainty, Goal, QueryResult}; -use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams}; +use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams, TreatProjections}; use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt}; use rustc_middle::ty::{TraitPredicate, TypeVisitableExt}; use rustc_span::DUMMY_SP; @@ -36,7 +36,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { let tcx = ecx.tcx(); let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap(); - let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::AsPlaceholder }; + let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::ForLookup }; if iter::zip(goal.predicate.trait_ref.substs, impl_trait_ref.skip_binder().substs) .any(|(goal, imp)| !drcx.generic_args_may_unify(goal, imp)) { @@ -135,9 +135,15 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { // currently instead lint patterns which can be used to // exploit this unsoundness on stable, see #93367 for // more details. + // + // Using `TreatProjections::NextSolverLookup` is fine here because + // `instantiate_constituent_tys_for_auto_trait` returns nothing for + // projection types anyways. So it doesn't really matter what we do + // here, and this is faster. if let Some(def_id) = ecx.tcx().find_map_relevant_impl( goal.predicate.def_id(), goal.predicate.self_ty(), + TreatProjections::NextSolverLookup, Some, ) { debug!(?def_id, ?goal, "disqualified auto-trait implementation"); diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 6b688c322c7..96a4b76af55 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -75,7 +75,7 @@ pub fn overlapping_impls( // Before doing expensive operations like entering an inference context, do // a quick check via fast_reject to tell if the impl headers could possibly // unify. - let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::AsInfer }; + let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::AsCandidateKey }; let impl1_ref = tcx.impl_trait_ref(impl1_def_id); let impl2_ref = tcx.impl_trait_ref(impl2_def_id); let may_overlap = match (impl1_ref, impl2_ref) { 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 704b0d0bd1c..41ffaeeac1c 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -32,6 +32,7 @@ use rustc_infer::infer::{InferOk, TypeTrace}; use rustc_middle::traits::select::OverflowError; use rustc_middle::ty::abstract_const::NotConstEvaluatable; use rustc_middle::ty::error::{ExpectedFound, TypeError}; +use rustc_middle::ty::fast_reject::TreatProjections; use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::print::{with_forced_trimmed_paths, FmtPrinter, Print}; use rustc_middle::ty::{ @@ -1799,12 +1800,17 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { }) .and_then(|(trait_assoc_item, id)| { let trait_assoc_ident = trait_assoc_item.ident(self.tcx); - self.tcx.find_map_relevant_impl(id, proj.projection_ty.self_ty(), |did| { - self.tcx - .associated_items(did) - .in_definition_order() - .find(|assoc| assoc.ident(self.tcx) == trait_assoc_ident) - }) + self.tcx.find_map_relevant_impl( + id, + proj.projection_ty.self_ty(), + TreatProjections::ForLookup, + |did| { + self.tcx + .associated_items(did) + .in_definition_order() + .find(|assoc| assoc.ident(self.tcx) == trait_assoc_ident) + }, + ) }) .and_then(|item| match self.tcx.hir().get_if_local(item.def_id) { Some( @@ -2176,7 +2182,12 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { trait_ref: &ty::PolyTraitRef<'tcx>, ) -> bool { let get_trait_impl = |trait_def_id| { - self.tcx.find_map_relevant_impl(trait_def_id, trait_ref.skip_binder().self_ty(), Some) + self.tcx.find_map_relevant_impl( + trait_def_id, + trait_ref.skip_binder().self_ty(), + TreatProjections::ForLookup, + Some, + ) }; let required_trait_path = self.tcx.def_path_str(trait_ref.def_id()); let traits_with_same_path: std::collections::BTreeSet<_> = self diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index e91057356a2..3182af989f0 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -9,6 +9,7 @@ use hir::LangItem; use rustc_hir as hir; use rustc_infer::traits::ObligationCause; use rustc_infer::traits::{Obligation, SelectionError, TraitObligation}; +use rustc_middle::ty::fast_reject::TreatProjections; use rustc_middle::ty::{self, Ty, TypeVisitableExt}; use rustc_target::spec::abi::Abi; @@ -783,6 +784,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let relevant_impl = self.tcx().find_map_relevant_impl( self.tcx().require_lang_item(LangItem::Drop, None), obligation.predicate.skip_binder().trait_ref.self_ty(), + TreatProjections::ForLookup, Some, ); diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index d7ce0078124..38cdaddc1e7 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2558,7 +2558,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { // We can avoid creating type variables and doing the full // substitution if we find that any of the input types, when // simplified, do not match. - let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::AsPlaceholder }; + let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::ForLookup }; iter::zip(obligation.predicate.skip_binder().trait_ref.substs, impl_trait_ref.substs) .any(|(obl, imp)| !drcx.generic_args_may_unify(obl, imp)) } diff --git a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs index 61ed9ef2ec1..cd665d9471d 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs @@ -3,7 +3,7 @@ use super::OverlapError; use crate::traits; use rustc_errors::ErrorGuaranteed; use rustc_hir::def_id::DefId; -use rustc_middle::ty::fast_reject::{self, SimplifiedType, TreatParams}; +use rustc_middle::ty::fast_reject::{self, SimplifiedType, TreatParams, TreatProjections}; use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt}; pub use rustc_middle::traits::specialization_graph::*; @@ -49,8 +49,12 @@ impl<'tcx> ChildrenExt<'tcx> for Children { /// Insert an impl into this set of children without comparing to any existing impls. fn insert_blindly(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) { let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().skip_binder(); - if let Some(st) = fast_reject::simplify_type(tcx, trait_ref.self_ty(), TreatParams::AsInfer) - { + if let Some(st) = fast_reject::simplify_type( + tcx, + trait_ref.self_ty(), + TreatParams::AsCandidateKey, + TreatProjections::AsCandidateKey, + ) { debug!("insert_blindly: impl_def_id={:?} st={:?}", impl_def_id, st); self.non_blanket_impls.entry(st).or_default().push(impl_def_id) } else { @@ -65,8 +69,12 @@ impl<'tcx> ChildrenExt<'tcx> for Children { fn remove_existing(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) { let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().skip_binder(); let vec: &mut Vec<DefId>; - if let Some(st) = fast_reject::simplify_type(tcx, trait_ref.self_ty(), TreatParams::AsInfer) - { + if let Some(st) = fast_reject::simplify_type( + tcx, + trait_ref.self_ty(), + TreatParams::AsCandidateKey, + TreatProjections::AsCandidateKey, + ) { debug!("remove_existing: impl_def_id={:?} st={:?}", impl_def_id, st); vec = self.non_blanket_impls.get_mut(&st).unwrap(); } else { @@ -302,7 +310,12 @@ impl<'tcx> GraphExt<'tcx> for Graph { let mut parent = trait_def_id; let mut last_lint = None; - let simplified = fast_reject::simplify_type(tcx, trait_ref.self_ty(), TreatParams::AsInfer); + let simplified = fast_reject::simplify_type( + tcx, + trait_ref.self_ty(), + TreatParams::AsCandidateKey, + TreatProjections::AsCandidateKey, + ); // Descend the specialization tree, where `parent` is the current parent node. loop { |
