diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index f458ff01c10..0f0facdca65 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -78,7 +78,7 @@ pub fn provide(providers: &mut Providers) { trait_def, adt_def, fn_sig, - impl_trait_ref, + impl_trait_header, impl_polarity, coroutine_kind, coroutine_for_closure, @@ -598,7 +598,7 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { hir::ItemKind::Impl { .. } => { tcx.ensure().generics_of(def_id); tcx.ensure().type_of(def_id); - tcx.ensure().impl_trait_ref(def_id); + tcx.ensure().impl_trait_header(def_id); tcx.ensure().predicates_of(def_id); } hir::ItemKind::Trait(..) => { @@ -1323,19 +1323,20 @@ fn suggest_impl_trait<'tcx>( None } -fn impl_trait_ref( +fn impl_trait_header( tcx: TyCtxt<'_>, def_id: LocalDefId, -) -> Option>> { +) -> Option<(ty::EarlyBinder>, ty::ImplPolarity)> { let icx = ItemCtxt::new(tcx, def_id); - let impl_ = tcx.hir().expect_item(def_id).expect_impl(); + let item = tcx.hir().expect_item(def_id); + let impl_ = item.expect_impl(); impl_ .of_trait .as_ref() .map(|ast_trait_ref| { let selfty = tcx.type_of(def_id).instantiate_identity(); - if let Some(ErrorGuaranteed { .. }) = check_impl_constness( + let impl_trait_ref = if let Some(ErrorGuaranteed { .. }) = check_impl_constness( tcx, tcx.is_const_trait_impl_raw(def_id.to_def_id()), ast_trait_ref, @@ -1360,9 +1361,9 @@ fn impl_trait_ref( icx.astconv().instantiate_mono_trait_ref(trait_ref, selfty) } else { icx.astconv().instantiate_mono_trait_ref(ast_trait_ref, selfty) - } + }; + (ty::EarlyBinder::bind(impl_trait_ref), polarity_of_impl(tcx, def_id, impl_, item.span)) }) - .map(ty::EarlyBinder::bind) } fn check_impl_constness( @@ -1391,42 +1392,38 @@ fn check_impl_constness( } fn impl_polarity(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::ImplPolarity { - let is_rustc_reservation = tcx.has_attr(def_id, sym::rustc_reservation_impl); let item = tcx.hir().expect_item(def_id); - match &item.kind { - hir::ItemKind::Impl(hir::Impl { - polarity: hir::ImplPolarity::Negative(span), - of_trait, - .. - }) => { + polarity_of_impl(tcx, def_id, item.expect_impl(), item.span) +} + +fn polarity_of_impl( + tcx: TyCtxt<'_>, + def_id: LocalDefId, + impl_: &hir::Impl<'_>, + span: Span, +) -> ty::ImplPolarity { + let is_rustc_reservation = tcx.has_attr(def_id, sym::rustc_reservation_impl); + match &impl_ { + hir::Impl { polarity: hir::ImplPolarity::Negative(span), of_trait, .. } => { if is_rustc_reservation { let span = span.to(of_trait.as_ref().map_or(*span, |t| t.path.span)); tcx.dcx().span_err(span, "reservation impls can't be negative"); } ty::ImplPolarity::Negative } - hir::ItemKind::Impl(hir::Impl { - polarity: hir::ImplPolarity::Positive, - of_trait: None, - .. - }) => { + hir::Impl { polarity: hir::ImplPolarity::Positive, of_trait: None, .. } => { if is_rustc_reservation { - tcx.dcx().span_err(item.span, "reservation impls can't be inherent"); + tcx.dcx().span_err(span, "reservation impls can't be inherent"); } ty::ImplPolarity::Positive } - hir::ItemKind::Impl(hir::Impl { - polarity: hir::ImplPolarity::Positive, - of_trait: Some(_), - .. - }) => { + hir::Impl { polarity: hir::ImplPolarity::Positive, of_trait: Some(_), .. } => { if is_rustc_reservation { ty::ImplPolarity::Reservation } else { ty::ImplPolarity::Positive } } - item => bug!("impl_polarity: {:?} not an impl", item), } } diff --git a/compiler/rustc_incremental/src/persist/dirty_clean.rs b/compiler/rustc_incremental/src/persist/dirty_clean.rs index 14cc8c260e2..8311a735133 100644 --- a/compiler/rustc_incremental/src/persist/dirty_clean.rs +++ b/compiler/rustc_incremental/src/persist/dirty_clean.rs @@ -63,7 +63,7 @@ /// `impl` implementation of struct/trait const BASE_IMPL: &[&str] = - &[label_strs::associated_item_def_ids, label_strs::generics_of, label_strs::impl_trait_ref]; + &[label_strs::associated_item_def_ids, label_strs::generics_of, label_strs::impl_trait_header]; /// DepNodes for mir_built/Optimized, which is relevant in "executable" /// code, i.e., functions+methods diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 988388edfd5..058f28a3ee9 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -215,7 +215,7 @@ fn into_args(self) -> (DefId, SimplifiedType) { variances_of => { table } fn_sig => { table } codegen_fn_attrs => { table } - impl_trait_ref => { table } + impl_trait_header => { table } const_param_default => { table } object_lifetime_default => { table } thir_abstract_const => { table } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 6ca1973396f..361c0a3f87e 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1971,8 +1971,9 @@ fn encode_impls(&mut self) -> LazyArray { self.tables.defaultness.set_some(def_id.index, tcx.defaultness(def_id)); self.tables.impl_polarity.set_some(def_id.index, tcx.impl_polarity(def_id)); - if of_trait && let Some(trait_ref) = tcx.impl_trait_ref(def_id) { - record!(self.tables.impl_trait_ref[def_id] <- trait_ref); + if of_trait && let Some(header) = tcx.impl_trait_header(def_id) { + record!(self.tables.impl_trait_header[def_id] <- header); + let (trait_ref, _polarity) = header; let trait_ref = trait_ref.instantiate_identity(); let simplified_self_ty = fast_reject::simplify_type( diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 8205e995c19..f2d4ae11105 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -423,7 +423,7 @@ fn encode(&self, buf: &mut FileEncoder) -> LazyTables { variances_of: Table>, fn_sig: Table>>>, codegen_fn_attrs: Table>, - impl_trait_ref: Table>>>, + impl_trait_header: Table>, ty::ImplPolarity)>>, const_param_default: Table>>>, object_lifetime_default: Table>, optimized_mir: Table>>, diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index a272a51f327..e15a051b33f 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -177,8 +177,9 @@ impl EraseType for Option> { type Result = [u8; size_of::>>()]; } -impl EraseType for Option>> { - type Result = [u8; size_of::>>>()]; +impl EraseType for Option<(ty::EarlyBinder>, ty::ImplPolarity)> { + type Result = + [u8; size_of::>, ty::ImplPolarity)>>()]; } impl EraseType for Option>> { diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 938fba0ed09..59fb198a3da 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -846,9 +846,9 @@ cache_on_disk_if { true } } - /// Given an `impl_id`, return the trait it implements. + /// 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_ref(impl_id: DefId) -> Option>> { + query impl_trait_header(impl_id: DefId) -> Option<(ty::EarlyBinder>, ty::ImplPolarity)> { 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 b747f0a4fb6..c3b69cee9ed 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -2308,6 +2308,15 @@ pub fn is_impl_trait_in_trait(self, def_id: DefId) -> bool { pub fn module_children_local(self, def_id: LocalDefId) -> &'tcx [ModChild] { self.resolutions(()).module_children.get(&def_id).map_or(&[], |v| &v[..]) } + + /// Given an `impl_id`, return the trait it implements. + /// Return `None` if this is an inherent impl. + pub fn impl_trait_ref( + self, + def_id: impl IntoQueryParam, + ) -> Option>> { + Some(self.impl_trait_header(def_id)?.0) + } } /// Parameter attributes that can only be determined by examining the body of a function instead diff --git a/tests/incremental/hashes/trait_impls.rs b/tests/incremental/hashes/trait_impls.rs index 2e97a35d36b..e103be0a085 100644 --- a/tests/incremental/hashes/trait_impls.rs +++ b/tests/incremental/hashes/trait_impls.rs @@ -462,9 +462,9 @@ fn id(t: u32) -> u32 { t } } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="opt_hir_owner_nodes,generics_of,impl_trait_ref", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,generics_of,impl_trait_header", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="opt_hir_owner_nodes,generics_of,impl_trait_ref", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,generics_of,impl_trait_header", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl AddTypeParameterToImpl for Bar { #[rustc_clean( @@ -493,9 +493,9 @@ fn id(self) -> Self { self } } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="opt_hir_owner_nodes,impl_trait_ref", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,impl_trait_header", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="opt_hir_owner_nodes,impl_trait_ref", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,impl_trait_header", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl ChangeSelfTypeOfImpl for u64 { #[rustc_clean(except="fn_sig,typeck,optimized_mir", cfg="cfail2")]