diff --git a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs index 35c3e3ed3150..530d8d4b1fa6 100644 --- a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs @@ -7,7 +7,7 @@ use rustc_middle::ty::TyCtxt; fn parent_impl_or_trait_constness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Constness { let parent_id = tcx.local_parent(def_id); match tcx.def_kind(parent_id) { - DefKind::Impl { of_trait: true } => tcx.impl_trait_header(parent_id).unwrap().constness, + DefKind::Impl { of_trait: true } => tcx.impl_trait_header(parent_id).constness, DefKind::Trait => { if tcx.is_const_trait(parent_id.into()) { hir::Constness::Const diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index c59ed39ae211..95b47c8aba67 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -806,10 +806,10 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), DefKind::Impl { of_trait } => { tcx.ensure_ok().generics_of(def_id); tcx.ensure_ok().type_of(def_id); - tcx.ensure_ok().impl_trait_header(def_id); tcx.ensure_ok().predicates_of(def_id); tcx.ensure_ok().associated_items(def_id); - if of_trait && let Some(impl_trait_header) = tcx.impl_trait_header(def_id) { + if of_trait { + let impl_trait_header = tcx.impl_trait_header(def_id); res = res.and( tcx.ensure_ok() .coherent_trait(impl_trait_header.trait_ref.instantiate_identity().def_id), diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 5649a6e9a3d8..f3d6398b2085 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -248,7 +248,7 @@ pub(super) fn check_item<'tcx>( crate::impl_wf_check::check_impl_wf(tcx, def_id, impl_.of_trait.is_some())?; let mut res = Ok(()); if let Some(of_trait) = impl_.of_trait { - let header = tcx.impl_trait_header(def_id).unwrap(); + let header = tcx.impl_trait_header(def_id); let is_auto = tcx.trait_is_auto(header.trait_ref.skip_binder().def_id); if let (hir::Defaultness::Default { .. }, true) = (of_trait.defaultness, is_auto) { let sp = of_trait.trait_ref.path.span; diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs index fbb442440bea..bc3231cff9b4 100644 --- a/compiler/rustc_hir_analysis/src/coherence/mod.rs +++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs @@ -163,7 +163,7 @@ fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) -> Result<(), ErrorGuaranteed> let mut res = tcx.ensure_ok().specialization_graph_of(def_id); for &impl_def_id in impls { - let impl_header = tcx.impl_trait_header(impl_def_id).unwrap(); + let impl_header = tcx.impl_trait_header(impl_def_id); let trait_ref = impl_header.trait_ref.instantiate_identity(); let trait_def = tcx.trait_def(trait_ref.def_id); diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index b6a662f42560..89ab710ff821 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1291,28 +1291,26 @@ pub fn suggest_impl_trait<'tcx>( None } -fn impl_trait_header(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option> { +fn impl_trait_header(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::ImplTraitHeader<'_> { let icx = ItemCtxt::new(tcx, def_id); let item = tcx.hir_expect_item(def_id); let impl_ = item.expect_impl(); + let of_trait = impl_ + .of_trait + .unwrap_or_else(|| panic!("expected impl trait, found inherent impl on {def_id:?}")); + let selfty = tcx.type_of(def_id).instantiate_identity(); let is_rustc_reservation = tcx.has_attr(def_id, sym::rustc_reservation_impl); - if is_rustc_reservation && impl_.of_trait.is_none() { - tcx.dcx().span_err(item.span, "reservation impls can't be inherent"); + + check_impl_constness(tcx, of_trait.constness, &of_trait.trait_ref); + + let trait_ref = icx.lowerer().lower_impl_trait_ref(&of_trait.trait_ref, selfty); + + ty::ImplTraitHeader { + trait_ref: ty::EarlyBinder::bind(trait_ref), + safety: of_trait.safety, + polarity: polarity_of_impl(tcx, of_trait, is_rustc_reservation), + constness: of_trait.constness, } - impl_.of_trait.map(|of_trait| { - let selfty = tcx.type_of(def_id).instantiate_identity(); - - check_impl_constness(tcx, of_trait.constness, &of_trait.trait_ref); - - let trait_ref = icx.lowerer().lower_impl_trait_ref(&of_trait.trait_ref, selfty); - - ty::ImplTraitHeader { - trait_ref: ty::EarlyBinder::bind(trait_ref), - safety: of_trait.safety, - polarity: polarity_of_impl(tcx, of_trait, is_rustc_reservation), - constness: of_trait.constness, - } - }) } fn check_impl_constness( diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs index 129b26d8ff0c..67284e162156 100644 --- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs +++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs @@ -514,17 +514,15 @@ pub(super) fn impl_super_outlives( tcx: TyCtxt<'_>, def_id: DefId, ) -> ty::EarlyBinder<'_, ty::Clauses<'_>> { - tcx.impl_trait_header(def_id).expect("expected an impl of trait").trait_ref.map_bound( - |trait_ref| { - let clause: ty::Clause<'_> = trait_ref.upcast(tcx); - tcx.mk_clauses_from_iter(util::elaborate(tcx, [clause]).filter(|clause| { - matches!( - clause.kind().skip_binder(), - ty::ClauseKind::TypeOutlives(_) | ty::ClauseKind::RegionOutlives(_) - ) - })) - }, - ) + tcx.impl_trait_header(def_id).trait_ref.map_bound(|trait_ref| { + let clause: ty::Clause<'_> = trait_ref.upcast(tcx); + tcx.mk_clauses_from_iter(util::elaborate(tcx, [clause]).filter(|clause| { + matches!( + clause.kind().skip_binder(), + ty::ClauseKind::TypeOutlives(_) | ty::ClauseKind::RegionOutlives(_) + ) + })) + }) } struct AssocTyToOpaque<'tcx> { diff --git a/compiler/rustc_hir_analysis/src/delegation.rs b/compiler/rustc_hir_analysis/src/delegation.rs index f5821aed03f2..125fc21a5cc1 100644 --- a/compiler/rustc_hir_analysis/src/delegation.rs +++ b/compiler/rustc_hir_analysis/src/delegation.rs @@ -272,8 +272,7 @@ fn create_generic_args<'tcx>( (FnKind::AssocTraitImpl, FnKind::AssocTrait) => { let callee_generics = tcx.generics_of(sig_id); let parent = tcx.parent(def_id.into()); - let parent_args = - tcx.impl_trait_header(parent).unwrap().trait_ref.instantiate_identity().args; + let parent_args = tcx.impl_trait_header(parent).trait_ref.instantiate_identity().args; let trait_args = ty::GenericArgs::identity_for_item(tcx, sig_id); let method_args = tcx.mk_args(&trait_args[callee_generics.parent_count..]); diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index 165051744641..25ba888e9460 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -473,7 +473,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } else { // Find all the types that have an `impl` for the trait. tcx.all_impls(trait_def_id) - .filter_map(|impl_def_id| tcx.impl_trait_header(impl_def_id)) + .map(|impl_def_id| tcx.impl_trait_header(impl_def_id)) .filter(|header| { // Consider only accessible traits tcx.visibility(trait_def_id).is_accessible_from(self.item_def_id(), tcx) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index e218bbf69f01..4ff8f5d9e9c7 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -1615,7 +1615,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .is_accessible_from(self.item_def_id(), tcx) && tcx.all_impls(*trait_def_id) .any(|impl_def_id| { - let header = tcx.impl_trait_header(impl_def_id).unwrap(); + let header = tcx.impl_trait_header(impl_def_id); let trait_ref = header.trait_ref.instantiate( tcx, infcx.fresh_args_for_item(DUMMY_SP, impl_def_id), diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 3f549bc6a372..aacd2f511a3c 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -3980,11 +3980,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if self .tcx .all_impls(candidate.def_id) - .map(|imp_did| { - self.tcx.impl_trait_header(imp_did).expect( - "inherent impls can't be candidates, only trait impls can be", - ) - }) + .map(|imp_did| self.tcx.impl_trait_header(imp_did)) .filter(|header| header.polarity != ty::ImplPolarity::Positive) .any(|header| { let imp = header.trait_ref.instantiate_identity(); diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index db66938457f0..e13ef7e70f44 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -2115,7 +2115,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { }; let def_id = id.owner_id.to_def_id(); - if of_trait && let Some(header) = tcx.impl_trait_header(def_id) { + if of_trait { + let header = tcx.impl_trait_header(def_id); record!(self.tables.impl_trait_header[def_id] <- header); self.tables.defaultness.set_some(def_id.index, tcx.defaultness(def_id)); diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index cad10fcfb010..fd46a65f2bbe 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -200,8 +200,8 @@ impl EraseType for Option> { type Result = [u8; size_of::>>()]; } -impl EraseType for Option> { - type Result = [u8; size_of::>>()]; +impl EraseType for ty::ImplTraitHeader<'_> { + type Result = [u8; size_of::>()]; } impl EraseType for Option>> { diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 448c26ef3181..3c4a4d229a3d 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1104,8 +1104,7 @@ rustc_queries! { } /// Given an `impl_id`, return the trait it implements along with some header information. - /// Return `None` if this is an inherent impl. - query impl_trait_header(impl_id: DefId) -> Option> { + query impl_trait_header(impl_id: DefId) -> ty::ImplTraitHeader<'tcx> { desc { |tcx| "computing trait implemented by `{}`", tcx.def_path_str(impl_id) } cache_on_disk_if { impl_id.is_local() } separate_provide_extern diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 29f6281798bd..545235c46c62 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -3472,7 +3472,7 @@ impl<'tcx> TyCtxt<'tcx> { /// Whether the trait impl is marked const. This does not consider stability or feature gates. pub fn is_const_trait_impl(self, def_id: DefId) -> bool { self.def_kind(def_id) == DefKind::Impl { of_trait: true } - && self.impl_trait_header(def_id).unwrap().constness == hir::Constness::Const + && self.impl_trait_header(def_id).constness == hir::Constness::Const } pub fn is_sdylib_interface_build(self) -> bool { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index dd8c51f2af81..5ca631f3d33f 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1614,8 +1614,8 @@ impl<'tcx> TyCtxt<'tcx> { def_id1: DefId, def_id2: DefId, ) -> Option { - let impl1 = self.impl_trait_header(def_id1).unwrap(); - let impl2 = self.impl_trait_header(def_id2).unwrap(); + let impl1 = self.impl_trait_header(def_id1); + let impl2 = self.impl_trait_header(def_id2); let trait_ref1 = impl1.trait_ref.skip_binder(); let trait_ref2 = impl2.trait_ref.skip_binder(); @@ -1973,7 +1973,7 @@ impl<'tcx> TyCtxt<'tcx> { } pub fn impl_polarity(self, def_id: impl IntoQueryParam) -> ty::ImplPolarity { - self.impl_trait_header(def_id).map_or(ty::ImplPolarity::Positive, |h| h.polarity) + self.impl_trait_header(def_id).polarity } /// Given an `impl_id`, return the trait it implements. @@ -1981,7 +1981,7 @@ impl<'tcx> TyCtxt<'tcx> { self, def_id: impl IntoQueryParam, ) -> ty::EarlyBinder<'tcx, ty::TraitRef<'tcx>> { - self.impl_opt_trait_ref(def_id).unwrap() + self.impl_trait_header(def_id).trait_ref } /// Given an `impl_id`, return the trait it implements. @@ -1990,7 +1990,8 @@ impl<'tcx> TyCtxt<'tcx> { self, def_id: impl IntoQueryParam, ) -> Option>> { - self.impl_trait_header(def_id).map(|header| header.trait_ref) + let def_id = def_id.into_query_param(); + self.impl_is_of_trait(def_id).then(|| self.impl_trait_ref(def_id)) } /// Given the `DefId` of an impl, returns the `DefId` of the trait it implements. @@ -2097,7 +2098,7 @@ impl<'tcx> TyCtxt<'tcx> { let def_id: DefId = def_id.into(); match self.def_kind(def_id) { DefKind::Impl { of_trait: true } => { - let header = self.impl_trait_header(def_id).unwrap(); + let header = self.impl_trait_header(def_id); header.constness == hir::Constness::Const && self.is_const_trait(header.trait_ref.skip_binder().def_id) } diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 2169ed3c254b..93f647c05e02 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -1568,7 +1568,7 @@ impl<'v> RootCollector<'_, 'v> { } } } - DefKind::Impl { .. } => { + DefKind::Impl { of_trait: true } => { if self.strategy == MonoItemCollectionStrategy::Eager { create_mono_items_for_default_impls(self.tcx, id, self.output); } @@ -1715,9 +1715,7 @@ fn create_mono_items_for_default_impls<'tcx>( item: hir::ItemId, output: &mut MonoItems<'tcx>, ) { - let Some(impl_) = tcx.impl_trait_header(item.owner_id) else { - return; - }; + let impl_ = tcx.impl_trait_header(item.owner_id); if matches!(impl_.polarity, ty::ImplPolarity::Negative) { return; diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs index a0cc6091866d..eb72f71382ef 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs @@ -57,7 +57,7 @@ pub fn compute_applicable_impls_for_diagnostics<'tcx>( return false; } - let impl_trait_header = tcx.impl_trait_header(impl_def_id).unwrap(); + let impl_trait_header = tcx.impl_trait_header(impl_def_id); let impl_polarity = impl_trait_header.polarity; match (impl_polarity, predicate_polarity) { diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 4305d4160ebf..373819d96f4a 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -1867,7 +1867,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { .tcx .all_impls(trait_pred.def_id()) .filter_map(|def_id| { - let imp = self.tcx.impl_trait_header(def_id).unwrap(); + let imp = self.tcx.impl_trait_header(def_id); if imp.polarity != ty::ImplPolarity::Positive || !self.tcx.is_user_visible_dep(def_id.krate) { @@ -1906,7 +1906,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // ignore `do_not_recommend` items .filter(|def_id| !self.tcx.do_not_recommend_impl(*def_id)) // Ignore automatically derived impls and `!Trait` impls. - .filter_map(|def_id| self.tcx.impl_trait_header(def_id)) + .map(|def_id| self.tcx.impl_trait_header(def_id)) .filter_map(|header| { (header.polarity != ty::ImplPolarity::Negative || self.tcx.is_automatically_derived(def_id)) diff --git a/compiler/rustc_trait_selection/src/traits/effects.rs b/compiler/rustc_trait_selection/src/traits/effects.rs index d694a092853a..7f2a9999d646 100644 --- a/compiler/rustc_trait_selection/src/traits/effects.rs +++ b/compiler/rustc_trait_selection/src/traits/effects.rs @@ -458,9 +458,7 @@ fn evaluate_host_effect_from_selection_candidate<'tcx>( Err(_) => Err(EvaluationFailure::NoSolution), Ok(Some(source)) => match source { ImplSource::UserDefined(impl_) => { - if tcx.impl_trait_header(impl_.impl_def_id).unwrap().constness - != hir::Constness::Const - { + if tcx.impl_trait_header(impl_.impl_def_id).constness != hir::Constness::Const { return Err(EvaluationFailure::NoSolution); } 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 cb980d5ce8b4..cecb43e537a8 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -604,7 +604,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Before we create the generic parameters and everything, first // consider a "quick reject". This avoids creating more types // and so forth that we need to. - let impl_trait_header = self.tcx().impl_trait_header(impl_def_id).unwrap(); + let impl_trait_header = self.tcx().impl_trait_header(impl_def_id); if !drcx .args_may_unify(obligation_args, impl_trait_header.trait_ref.skip_binder().args) { diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 9be5d0673f73..614c09d913f7 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2487,7 +2487,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { impl_def_id: DefId, obligation: &PolyTraitObligation<'tcx>, ) -> Normalized<'tcx, GenericArgsRef<'tcx>> { - let impl_trait_header = self.tcx().impl_trait_header(impl_def_id).unwrap(); + let impl_trait_header = self.tcx().impl_trait_header(impl_def_id); match self.match_impl(impl_def_id, impl_trait_header, obligation) { Ok(args) => args, Err(()) => { diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index a00680b47134..ca6fd780dd88 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -252,7 +252,7 @@ pub(super) fn specializes( } } - let specializing_impl_trait_header = tcx.impl_trait_header(specializing_impl_def_id).unwrap(); + let specializing_impl_trait_header = tcx.impl_trait_header(specializing_impl_def_id); // We determine whether there's a subset relationship by: // diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 1cd4b880abe7..b470af50f68f 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -566,7 +566,11 @@ pub(crate) fn build_impl( clean::enter_impl_trait(cx, |cx| clean_ty_generics(cx, did)), ), }; - let polarity = tcx.impl_polarity(did); + let polarity = if associated_trait.is_some() { + tcx.impl_polarity(did) + } else { + ty::ImplPolarity::Positive + }; let trait_ = associated_trait .map(|t| clean_trait_ref_with_constraints(cx, ty::Binder::dummy(t), ThinVec::new())); if trait_.as_ref().map(|t| t.def_id()) == tcx.lang_items().deref_trait() { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 481395ffb836..4a95f21a3a5b 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2934,7 +2934,11 @@ fn clean_impl<'tcx>( trait_, for_, items, - polarity: tcx.impl_polarity(def_id), + polarity: if impl_.of_trait.is_some() { + tcx.impl_polarity(def_id) + } else { + ty::ImplPolarity::Positive + }, kind: if utils::has_doc_flag(tcx, def_id.to_def_id(), sym::fake_variadic) { ImplKind::FakeVariadic } else {