Auto merge of #114852 - GuillaumeGomez:rollup-vjagxjr, r=GuillaumeGomez
Rollup of 10 pull requests Successful merges: - #114711 (Infer `Lld::No` linker hint when the linker stem is a generic compiler driver) - #114772 (Add `{Local}ModDefId` to more strongly type DefIds`) - #114800 (std: add some missing repr(transparent)) - #114820 (Add test for unknown_lints from another file.) - #114825 (Upgrade std to gimli 0.28.0) - #114827 (Only consider object candidates for object-safe dyn types in new solver) - #114828 (Probe when assembling upcast candidates so they don't step on eachother's toes in new solver) - #114829 (Separate `consider_unsize_to_dyn_candidate` from other unsize candidates) - #114830 (Clean up some bad UI testing annotations) - #114831 (Check projection args before substitution in new solver) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
c57393e4f8
@ -2991,25 +2991,10 @@ fn add_lld_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) {
|
||||
return;
|
||||
}
|
||||
|
||||
let self_contained_linker = sess.opts.cg.link_self_contained.linker();
|
||||
|
||||
// FIXME: some targets default to using `lld`, but users can only override the linker on the CLI
|
||||
// and cannot yet select the precise linker flavor to opt out of that. See for example issue
|
||||
// #113597 for the `thumbv6m-none-eabi` target: a driver is used, and its default linker
|
||||
// conflicts with the target's flavor, causing unexpected arguments being passed.
|
||||
//
|
||||
// Until the new `LinkerFlavor`-like CLI options are stabilized, we only adopt MCP510's behavior
|
||||
// if its dedicated unstable CLI flags are used, to keep the current sub-optimal stable
|
||||
// behavior.
|
||||
let using_mcp510 =
|
||||
self_contained_linker || sess.opts.cg.linker_flavor.is_some_and(|f| f.is_unstable());
|
||||
if !using_mcp510 && !unstable_use_lld {
|
||||
return;
|
||||
}
|
||||
|
||||
// 1. Implement the "self-contained" part of this feature by adding rustc distribution
|
||||
// directories to the tool's search path.
|
||||
if self_contained_linker || unstable_use_lld {
|
||||
let self_contained_linker = sess.opts.cg.link_self_contained.linker() || unstable_use_lld;
|
||||
if self_contained_linker {
|
||||
for path in sess.get_tools_search_paths(false) {
|
||||
cmd.arg({
|
||||
let mut arg = OsString::from("-B");
|
||||
|
@ -8,7 +8,7 @@ use rustc_attr as attr;
|
||||
use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{CtorKind, DefKind, Res};
|
||||
use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
|
||||
use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId};
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
use rustc_hir::{ItemKind, Node, PathSegment};
|
||||
use rustc_infer::infer::opaque_types::ConstrainOpaqueTypeRegionVisitor;
|
||||
@ -1443,12 +1443,12 @@ pub(super) fn check_type_params_are_used<'tcx>(
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn check_mod_item_types(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
|
||||
pub(super) fn check_mod_item_types(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
|
||||
let module = tcx.hir_module_items(module_def_id);
|
||||
for id in module.items() {
|
||||
check_item_type(tcx, id);
|
||||
}
|
||||
if module_def_id == CRATE_DEF_ID {
|
||||
if module_def_id == LocalModDefId::CRATE_DEF_ID {
|
||||
super::entry::check_for_entry_fn(tcx);
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ use rustc_ast as ast;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
|
||||
use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId};
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_hir::ItemKind;
|
||||
use rustc_infer::infer::outlives::env::{OutlivesEnvironment, RegionBoundPairs};
|
||||
@ -1854,7 +1854,7 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_mod_type_wf(tcx: TyCtxt<'_>, module: LocalDefId) {
|
||||
fn check_mod_type_wf(tcx: TyCtxt<'_>, module: LocalModDefId) {
|
||||
let items = tcx.hir_module_items(module);
|
||||
items.par_items(|item| tcx.ensure().check_well_formed(item.owner_id));
|
||||
items.par_impl_items(|item| tcx.ensure().check_well_formed(item.owner_id));
|
||||
|
@ -22,7 +22,7 @@ use rustc_data_structures::captures::Captures;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_errors::{Applicability, DiagnosticBuilder, ErrorGuaranteed, StashKey};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId};
|
||||
use rustc_hir::intravisit::{self, Visitor};
|
||||
use rustc_hir::{GenericParamKind, Node};
|
||||
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
|
||||
@ -48,7 +48,7 @@ mod type_of;
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Main entry point
|
||||
|
||||
fn collect_mod_item_types(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
|
||||
fn collect_mod_item_types(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
|
||||
tcx.hir().visit_item_likes_in_module(module_def_id, &mut CollectItemTypesVisitor { tcx });
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,7 @@ use min_specialization::check_min_specialization;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_errors::struct_span_err;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_hir::def_id::{LocalDefId, LocalModDefId};
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
|
||||
use rustc_span::{Span, Symbol};
|
||||
@ -51,7 +51,7 @@ mod min_specialization;
|
||||
/// impl<'a> Trait<Foo> for Bar { type X = &'a i32; }
|
||||
/// // ^ 'a is unused and appears in assoc type, error
|
||||
/// ```
|
||||
fn check_mod_impl_wf(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
|
||||
fn check_mod_impl_wf(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
|
||||
let min_specialization = tcx.features().min_specialization;
|
||||
let module = tcx.hir_module_items(module_def_id);
|
||||
for id in module.items() {
|
||||
|
@ -19,7 +19,7 @@ use rustc_ast as ast;
|
||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||
use rustc_data_structures::sync::join;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_hir::def_id::{LocalDefId, LocalModDefId};
|
||||
use rustc_hir::intravisit as hir_visit;
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
use rustc_middle::hir::nested_filter;
|
||||
@ -338,7 +338,7 @@ crate::late_lint_methods!(impl_late_lint_pass, []);
|
||||
|
||||
pub fn late_lint_mod<'tcx, T: LateLintPass<'tcx> + 'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
module_def_id: LocalDefId,
|
||||
module_def_id: LocalModDefId,
|
||||
builtin_lints: T,
|
||||
) {
|
||||
let context = LateContext {
|
||||
@ -369,7 +369,7 @@ pub fn late_lint_mod<'tcx, T: LateLintPass<'tcx> + 'tcx>(
|
||||
|
||||
fn late_lint_mod_inner<'tcx, T: LateLintPass<'tcx>>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
module_def_id: LocalDefId,
|
||||
module_def_id: LocalModDefId,
|
||||
context: LateContext<'tcx>,
|
||||
pass: T,
|
||||
) {
|
||||
|
@ -90,7 +90,7 @@ use rustc_ast as ast;
|
||||
use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
|
||||
use rustc_fluent_macro::fluent_messages;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_hir::def_id::{LocalDefId, LocalModDefId};
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::lint::builtin::{
|
||||
@ -145,7 +145,7 @@ pub fn provide(providers: &mut Providers) {
|
||||
*providers = Providers { lint_mod, ..*providers };
|
||||
}
|
||||
|
||||
fn lint_mod(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
|
||||
fn lint_mod(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
|
||||
late_lint_mod(tcx, module_def_id, BuiltinCombinedModuleLateLintPass::new());
|
||||
}
|
||||
|
||||
|
@ -60,7 +60,7 @@ use crate::mir::mono::MonoItem;
|
||||
use crate::ty::TyCtxt;
|
||||
|
||||
use rustc_data_structures::fingerprint::Fingerprint;
|
||||
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
|
||||
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalModDefId, ModDefId, LOCAL_CRATE};
|
||||
use rustc_hir::definitions::DefPathHash;
|
||||
use rustc_hir::{HirId, ItemLocalId, OwnerId};
|
||||
use rustc_query_system::dep_graph::FingerprintStyle;
|
||||
@ -387,3 +387,53 @@ impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for HirId {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_for_typed_def_id {
|
||||
($Name:ident, $LocalName:ident) => {
|
||||
impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for $Name {
|
||||
#[inline(always)]
|
||||
fn fingerprint_style() -> FingerprintStyle {
|
||||
FingerprintStyle::DefPathHash
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
|
||||
self.to_def_id().to_fingerprint(tcx)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
|
||||
self.to_def_id().to_debug_str(tcx)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
|
||||
DefId::recover(tcx, dep_node).map($Name::new_unchecked)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for $LocalName {
|
||||
#[inline(always)]
|
||||
fn fingerprint_style() -> FingerprintStyle {
|
||||
FingerprintStyle::DefPathHash
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
|
||||
self.to_def_id().to_fingerprint(tcx)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
|
||||
self.to_def_id().to_debug_str(tcx)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
|
||||
LocalDefId::recover(tcx, dep_node).map($LocalName::new_unchecked)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl_for_typed_def_id! { ModDefId, LocalModDefId }
|
||||
|
@ -8,7 +8,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||
use rustc_data_structures::svh::Svh;
|
||||
use rustc_data_structures::sync::{par_for_each_in, DynSend, DynSync};
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
|
||||
use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId, LOCAL_CRATE};
|
||||
use rustc_hir::definitions::{DefKey, DefPath, DefPathData, DefPathHash};
|
||||
use rustc_hir::intravisit::{self, Visitor};
|
||||
use rustc_hir::*;
|
||||
@ -148,7 +148,7 @@ impl<'hir> Map<'hir> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn module_items(self, module: LocalDefId) -> impl Iterator<Item = ItemId> + 'hir {
|
||||
pub fn module_items(self, module: LocalModDefId) -> impl Iterator<Item = ItemId> + 'hir {
|
||||
self.tcx.hir_module_items(module).items()
|
||||
}
|
||||
|
||||
@ -169,8 +169,8 @@ impl<'hir> Map<'hir> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn local_def_id_to_hir_id(self, def_id: LocalDefId) -> HirId {
|
||||
self.tcx.local_def_id_to_hir_id(def_id)
|
||||
pub fn local_def_id_to_hir_id(self, def_id: impl Into<LocalDefId>) -> HirId {
|
||||
self.tcx.local_def_id_to_hir_id(def_id.into())
|
||||
}
|
||||
|
||||
/// Do not call this function directly. The query should be called.
|
||||
@ -529,8 +529,8 @@ impl<'hir> Map<'hir> {
|
||||
self.krate_attrs().iter().any(|attr| attr.has_name(sym::rustc_coherence_is_core))
|
||||
}
|
||||
|
||||
pub fn get_module(self, module: LocalDefId) -> (&'hir Mod<'hir>, Span, HirId) {
|
||||
let hir_id = HirId::make_owner(module);
|
||||
pub fn get_module(self, module: LocalModDefId) -> (&'hir Mod<'hir>, Span, HirId) {
|
||||
let hir_id = HirId::make_owner(module.to_local_def_id());
|
||||
match self.tcx.hir_owner(hir_id.owner).map(|o| o.node) {
|
||||
Some(OwnerNode::Item(&Item { span, kind: ItemKind::Mod(ref m), .. })) => {
|
||||
(m, span, hir_id)
|
||||
@ -542,7 +542,7 @@ impl<'hir> Map<'hir> {
|
||||
|
||||
/// Walks the contents of the local crate. See also `visit_all_item_likes_in_crate`.
|
||||
pub fn walk_toplevel_module(self, visitor: &mut impl Visitor<'hir>) {
|
||||
let (top_mod, span, hir_id) = self.get_module(CRATE_DEF_ID);
|
||||
let (top_mod, span, hir_id) = self.get_module(LocalModDefId::CRATE_DEF_ID);
|
||||
visitor.visit_mod(top_mod, span, hir_id);
|
||||
}
|
||||
|
||||
@ -595,7 +595,7 @@ impl<'hir> Map<'hir> {
|
||||
|
||||
/// This method is the equivalent of `visit_all_item_likes_in_crate` but restricted to
|
||||
/// item-likes in a single module.
|
||||
pub fn visit_item_likes_in_module<V>(self, module: LocalDefId, visitor: &mut V)
|
||||
pub fn visit_item_likes_in_module<V>(self, module: LocalModDefId, visitor: &mut V)
|
||||
where
|
||||
V: Visitor<'hir>,
|
||||
{
|
||||
@ -618,17 +618,19 @@ impl<'hir> Map<'hir> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn for_each_module(self, mut f: impl FnMut(LocalDefId)) {
|
||||
pub fn for_each_module(self, mut f: impl FnMut(LocalModDefId)) {
|
||||
let crate_items = self.tcx.hir_crate_items(());
|
||||
for module in crate_items.submodules.iter() {
|
||||
f(module.def_id)
|
||||
f(LocalModDefId::new_unchecked(module.def_id))
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn par_for_each_module(self, f: impl Fn(LocalDefId) + DynSend + DynSync) {
|
||||
pub fn par_for_each_module(self, f: impl Fn(LocalModDefId) + DynSend + DynSync) {
|
||||
let crate_items = self.tcx.hir_crate_items(());
|
||||
par_for_each_in(&crate_items.submodules[..], |module| f(module.def_id))
|
||||
par_for_each_in(&crate_items.submodules[..], |module| {
|
||||
f(LocalModDefId::new_unchecked(module.def_id))
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns an iterator for the nodes in the ancestor tree of the `current_id`
|
||||
@ -1324,7 +1326,7 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn hir_module_items(tcx: TyCtxt<'_>, module_id: LocalDefId) -> ModuleItems {
|
||||
pub(super) fn hir_module_items(tcx: TyCtxt<'_>, module_id: LocalModDefId) -> ModuleItems {
|
||||
let mut collector = ItemCollector::new(tcx, false);
|
||||
|
||||
let (hir_mod, span, hir_id) = tcx.hir().get_module(module_id);
|
||||
|
@ -11,7 +11,7 @@ use crate::ty::{EarlyBinder, ImplSubject, TyCtxt};
|
||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||
use rustc_data_structures::sync::{par_for_each_in, DynSend, DynSync};
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId};
|
||||
use rustc_hir::*;
|
||||
use rustc_query_system::ich::StableHashingContext;
|
||||
use rustc_span::{ExpnId, DUMMY_SP};
|
||||
@ -101,22 +101,22 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
map::Map { tcx: self }
|
||||
}
|
||||
|
||||
pub fn parent_module(self, id: HirId) -> LocalDefId {
|
||||
pub fn parent_module(self, id: HirId) -> LocalModDefId {
|
||||
if !id.is_owner() && self.def_kind(id.owner) == DefKind::Mod {
|
||||
id.owner.def_id
|
||||
LocalModDefId::new_unchecked(id.owner.def_id)
|
||||
} else {
|
||||
self.parent_module_from_def_id(id.owner.def_id)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parent_module_from_def_id(self, mut id: LocalDefId) -> LocalDefId {
|
||||
pub fn parent_module_from_def_id(self, mut id: LocalDefId) -> LocalModDefId {
|
||||
while let Some(parent) = self.opt_local_parent(id) {
|
||||
id = parent;
|
||||
if self.def_kind(id) == DefKind::Mod {
|
||||
break;
|
||||
}
|
||||
}
|
||||
id
|
||||
LocalModDefId::new_unchecked(id)
|
||||
}
|
||||
|
||||
pub fn impl_subject(self, def_id: DefId) -> EarlyBinder<ImplSubject<'tcx>> {
|
||||
|
@ -235,6 +235,7 @@ trivial! {
|
||||
rustc_hir::def_id::DefId,
|
||||
rustc_hir::def_id::DefIndex,
|
||||
rustc_hir::def_id::LocalDefId,
|
||||
rustc_hir::def_id::LocalModDefId,
|
||||
rustc_hir::def::DefKind,
|
||||
rustc_hir::Defaultness,
|
||||
rustc_hir::definitions::DefKey,
|
||||
|
@ -8,7 +8,7 @@ use crate::ty::fast_reject::SimplifiedType;
|
||||
use crate::ty::layout::{TyAndLayout, ValidityRequirement};
|
||||
use crate::ty::{self, Ty, TyCtxt};
|
||||
use crate::ty::{GenericArg, GenericArgsRef};
|
||||
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
|
||||
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalModDefId, ModDefId, LOCAL_CRATE};
|
||||
use rustc_hir::hir_id::{HirId, OwnerId};
|
||||
use rustc_query_system::query::{DefaultCacheSelector, SingleCacheSelector, VecCacheSelector};
|
||||
use rustc_span::symbol::{Ident, Symbol};
|
||||
@ -175,6 +175,41 @@ impl AsLocalKey for DefId {
|
||||
}
|
||||
}
|
||||
|
||||
impl Key for LocalModDefId {
|
||||
type CacheSelector = DefaultCacheSelector<Self>;
|
||||
|
||||
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
|
||||
tcx.def_span(*self)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn key_as_def_id(&self) -> Option<DefId> {
|
||||
Some(self.to_def_id())
|
||||
}
|
||||
}
|
||||
|
||||
impl Key for ModDefId {
|
||||
type CacheSelector = DefaultCacheSelector<Self>;
|
||||
|
||||
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
|
||||
tcx.def_span(*self)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn key_as_def_id(&self) -> Option<DefId> {
|
||||
Some(self.to_def_id())
|
||||
}
|
||||
}
|
||||
|
||||
impl AsLocalKey for ModDefId {
|
||||
type LocalKey = LocalModDefId;
|
||||
|
||||
#[inline(always)]
|
||||
fn as_local_key(&self) -> Option<Self::LocalKey> {
|
||||
self.as_local()
|
||||
}
|
||||
}
|
||||
|
||||
impl Key for SimplifiedType {
|
||||
type CacheSelector = DefaultCacheSelector<Self>;
|
||||
|
||||
|
@ -67,7 +67,7 @@ use rustc_errors::ErrorGuaranteed;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, DocLinkResMap};
|
||||
use rustc_hir::def_id::{
|
||||
CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId, LocalDefIdMap, LocalDefIdSet,
|
||||
CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId, LocalDefIdMap, LocalDefIdSet, LocalModDefId,
|
||||
};
|
||||
use rustc_hir::lang_items::{LangItem, LanguageItems};
|
||||
use rustc_hir::{Crate, ItemLocalId, TraitCandidate};
|
||||
@ -167,7 +167,7 @@ rustc_queries! {
|
||||
///
|
||||
/// This can be conveniently accessed by `tcx.hir().visit_item_likes_in_module`.
|
||||
/// Avoid calling this query directly.
|
||||
query hir_module_items(key: LocalDefId) -> &'tcx rustc_middle::hir::ModuleItems {
|
||||
query hir_module_items(key: LocalModDefId) -> &'tcx rustc_middle::hir::ModuleItems {
|
||||
arena_cache
|
||||
desc { |tcx| "getting HIR module items in `{}`", tcx.def_path_str(key) }
|
||||
cache_on_disk_if { true }
|
||||
@ -896,7 +896,7 @@ rustc_queries! {
|
||||
}
|
||||
|
||||
/// Performs lint checking for the module.
|
||||
query lint_mod(key: LocalDefId) -> () {
|
||||
query lint_mod(key: LocalModDefId) -> () {
|
||||
desc { |tcx| "linting {}", describe_as_module(key, tcx) }
|
||||
}
|
||||
|
||||
@ -905,35 +905,35 @@ rustc_queries! {
|
||||
}
|
||||
|
||||
/// Checks the attributes in the module.
|
||||
query check_mod_attrs(key: LocalDefId) -> () {
|
||||
query check_mod_attrs(key: LocalModDefId) -> () {
|
||||
desc { |tcx| "checking attributes in {}", describe_as_module(key, tcx) }
|
||||
}
|
||||
|
||||
/// Checks for uses of unstable APIs in the module.
|
||||
query check_mod_unstable_api_usage(key: LocalDefId) -> () {
|
||||
query check_mod_unstable_api_usage(key: LocalModDefId) -> () {
|
||||
desc { |tcx| "checking for unstable API usage in {}", describe_as_module(key, tcx) }
|
||||
}
|
||||
|
||||
/// Checks the const bodies in the module for illegal operations (e.g. `if` or `loop`).
|
||||
query check_mod_const_bodies(key: LocalDefId) -> () {
|
||||
query check_mod_const_bodies(key: LocalModDefId) -> () {
|
||||
desc { |tcx| "checking consts in {}", describe_as_module(key, tcx) }
|
||||
}
|
||||
|
||||
/// Checks the loops in the module.
|
||||
query check_mod_loops(key: LocalDefId) -> () {
|
||||
query check_mod_loops(key: LocalModDefId) -> () {
|
||||
desc { |tcx| "checking loops in {}", describe_as_module(key, tcx) }
|
||||
}
|
||||
|
||||
query check_mod_naked_functions(key: LocalDefId) -> () {
|
||||
query check_mod_naked_functions(key: LocalModDefId) -> () {
|
||||
desc { |tcx| "checking naked functions in {}", describe_as_module(key, tcx) }
|
||||
}
|
||||
|
||||
query check_mod_item_types(key: LocalDefId) -> () {
|
||||
query check_mod_item_types(key: LocalModDefId) -> () {
|
||||
desc { |tcx| "checking item types in {}", describe_as_module(key, tcx) }
|
||||
}
|
||||
|
||||
query check_mod_privacy(key: LocalDefId) -> () {
|
||||
desc { |tcx| "checking privacy in {}", describe_as_module(key, tcx) }
|
||||
query check_mod_privacy(key: LocalModDefId) -> () {
|
||||
desc { |tcx| "checking privacy in {}", describe_as_module(key.to_local_def_id(), tcx) }
|
||||
}
|
||||
|
||||
query check_liveness(key: LocalDefId) {
|
||||
@ -952,19 +952,19 @@ rustc_queries! {
|
||||
desc { "finding live symbols in crate" }
|
||||
}
|
||||
|
||||
query check_mod_deathness(key: LocalDefId) -> () {
|
||||
query check_mod_deathness(key: LocalModDefId) -> () {
|
||||
desc { |tcx| "checking deathness of variables in {}", describe_as_module(key, tcx) }
|
||||
}
|
||||
|
||||
query check_mod_impl_wf(key: LocalDefId) -> () {
|
||||
query check_mod_impl_wf(key: LocalModDefId) -> () {
|
||||
desc { |tcx| "checking that impls are well-formed in {}", describe_as_module(key, tcx) }
|
||||
}
|
||||
|
||||
query check_mod_type_wf(key: LocalDefId) -> () {
|
||||
query check_mod_type_wf(key: LocalModDefId) -> () {
|
||||
desc { |tcx| "checking that types are well-formed in {}", describe_as_module(key, tcx) }
|
||||
}
|
||||
|
||||
query collect_mod_item_types(key: LocalDefId) -> () {
|
||||
query collect_mod_item_types(key: LocalModDefId) -> () {
|
||||
desc { |tcx| "collecting item types in {}", describe_as_module(key, tcx) }
|
||||
}
|
||||
|
||||
|
@ -545,6 +545,7 @@ macro_rules! define_feedable {
|
||||
|
||||
mod sealed {
|
||||
use super::{DefId, LocalDefId, OwnerId};
|
||||
use rustc_hir::def_id::{LocalModDefId, ModDefId};
|
||||
|
||||
/// An analogue of the `Into` trait that's intended only for query parameters.
|
||||
///
|
||||
@ -588,6 +589,27 @@ mod sealed {
|
||||
self.to_def_id()
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoQueryParam<DefId> for ModDefId {
|
||||
#[inline(always)]
|
||||
fn into_query_param(self) -> DefId {
|
||||
self.to_def_id()
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoQueryParam<DefId> for LocalModDefId {
|
||||
#[inline(always)]
|
||||
fn into_query_param(self) -> DefId {
|
||||
self.to_def_id()
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoQueryParam<LocalDefId> for LocalModDefId {
|
||||
#[inline(always)]
|
||||
fn into_query_param(self) -> LocalDefId {
|
||||
self.into()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub use sealed::IntoQueryParam;
|
||||
|
@ -355,8 +355,8 @@ impl TyCtxt<'_> {
|
||||
|
||||
#[inline]
|
||||
#[track_caller]
|
||||
pub fn local_parent(self, id: LocalDefId) -> LocalDefId {
|
||||
self.parent(id.to_def_id()).expect_local()
|
||||
pub fn local_parent(self, id: impl Into<LocalDefId>) -> LocalDefId {
|
||||
self.parent(id.into().to_def_id()).expect_local()
|
||||
}
|
||||
|
||||
pub fn is_descendant_of(self, mut descendant: DefId, ancestor: DefId) -> bool {
|
||||
|
@ -329,7 +329,8 @@ impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for ty::Const<'tcx> {
|
||||
}
|
||||
|
||||
// This is only used by query descriptions
|
||||
pub fn describe_as_module(def_id: LocalDefId, tcx: TyCtxt<'_>) -> String {
|
||||
pub fn describe_as_module(def_id: impl Into<LocalDefId>, tcx: TyCtxt<'_>) -> String {
|
||||
let def_id = def_id.into();
|
||||
if def_id.is_top_level_module() {
|
||||
"top-level module".to_string()
|
||||
} else {
|
||||
|
@ -11,7 +11,7 @@ use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
|
||||
use rustc_data_structures::sso::SsoHashSet;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{self, CtorKind, DefKind, Namespace};
|
||||
use rustc_hir::def_id::{DefId, DefIdSet, CRATE_DEF_ID, LOCAL_CRATE};
|
||||
use rustc_hir::def_id::{DefId, DefIdSet, ModDefId, CRATE_DEF_ID, LOCAL_CRATE};
|
||||
use rustc_hir::definitions::{DefKey, DefPathData, DefPathDataName, DisambiguatedDefPathData};
|
||||
use rustc_hir::LangItem;
|
||||
use rustc_session::config::TrimmedDefPaths;
|
||||
@ -326,7 +326,8 @@ pub trait PrettyPrinter<'tcx>:
|
||||
{
|
||||
this
|
||||
.tcx()
|
||||
.module_children(visible_parent)
|
||||
// FIXME(typed_def_id): Further propagate ModDefId
|
||||
.module_children(ModDefId::new_unchecked(*visible_parent))
|
||||
.iter()
|
||||
.filter(|child| child.res.opt_def_id() == Some(def_id))
|
||||
.find(|child| child.vis.is_public() && child.ident.name != kw::Underscore)
|
||||
@ -551,7 +552,8 @@ pub trait PrettyPrinter<'tcx>:
|
||||
// that's public and whose identifier isn't `_`.
|
||||
let reexport = self
|
||||
.tcx()
|
||||
.module_children(visible_parent)
|
||||
// FIXME(typed_def_id): Further propagate ModDefId
|
||||
.module_children(ModDefId::new_unchecked(visible_parent))
|
||||
.iter()
|
||||
.filter(|child| child.res.opt_def_id() == Some(def_id))
|
||||
.find(|child| child.vis.is_public() && child.ident.name != kw::Underscore)
|
||||
|
@ -10,7 +10,7 @@ use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_errors::{Applicability, IntoDiagnosticArg, MultiSpan};
|
||||
use rustc_feature::{AttributeDuplicates, AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_hir::def_id::LocalModDefId;
|
||||
use rustc_hir::intravisit::{self, Visitor};
|
||||
use rustc_hir::{
|
||||
self, FnSig, ForeignItem, HirId, Item, ItemKind, TraitItem, CRATE_HIR_ID, CRATE_OWNER_ID,
|
||||
@ -2465,10 +2465,10 @@ fn check_non_exported_macro_for_invalid_attrs(tcx: TyCtxt<'_>, item: &Item<'_>)
|
||||
}
|
||||
}
|
||||
|
||||
fn check_mod_attrs(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
|
||||
fn check_mod_attrs(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
|
||||
let check_attr_visitor = &mut CheckAttrVisitor { tcx, abort: Cell::new(false) };
|
||||
tcx.hir().visit_item_likes_in_module(module_def_id, check_attr_visitor);
|
||||
if module_def_id.is_top_level_module() {
|
||||
if module_def_id.to_local_def_id().is_top_level_module() {
|
||||
check_attr_visitor.check_attributes(CRATE_HIR_ID, DUMMY_SP, Target::Mod, None);
|
||||
check_invalid_crate_level_attr(tcx, tcx.hir().krate_attrs());
|
||||
}
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
use rustc_attr as attr;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_hir::def_id::{LocalDefId, LocalModDefId};
|
||||
use rustc_hir::intravisit::{self, Visitor};
|
||||
use rustc_middle::hir::nested_filter;
|
||||
use rustc_middle::query::Providers;
|
||||
@ -55,7 +55,7 @@ impl NonConstExpr {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_mod_const_bodies(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
|
||||
fn check_mod_const_bodies(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
|
||||
let mut vis = CheckConstVisitor::new(tcx);
|
||||
tcx.hir().visit_item_likes_in_module(module_def_id, &mut vis);
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ use rustc_data_structures::unord::UnordSet;
|
||||
use rustc_errors::MultiSpan;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{CtorOf, DefKind, Res};
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId};
|
||||
use rustc_hir::intravisit::{self, Visitor};
|
||||
use rustc_hir::{Node, PatKind, TyKind};
|
||||
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
||||
@ -944,7 +944,7 @@ impl<'tcx> DeadVisitor<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalDefId) {
|
||||
fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) {
|
||||
let (live_symbols, ignored_derived_traits) = tcx.live_symbols_and_ignored_derived_traits(());
|
||||
let mut visitor = DeadVisitor { tcx, live_symbols, ignored_derived_traits };
|
||||
|
||||
@ -969,7 +969,7 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalDefId) {
|
||||
|
||||
if !live_symbols.contains(&item.owner_id.def_id) {
|
||||
let parent = tcx.local_parent(item.owner_id.def_id);
|
||||
if parent != module && !live_symbols.contains(&parent) {
|
||||
if parent != module.to_local_def_id() && !live_symbols.contains(&parent) {
|
||||
// We already have diagnosed something.
|
||||
continue;
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
use Context::*;
|
||||
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_hir::def_id::LocalModDefId;
|
||||
use rustc_hir::intravisit::{self, Visitor};
|
||||
use rustc_hir::{Destination, Movability, Node};
|
||||
use rustc_middle::hir::map::Map;
|
||||
@ -34,7 +34,7 @@ struct CheckLoopVisitor<'a, 'hir> {
|
||||
cx: Context,
|
||||
}
|
||||
|
||||
fn check_mod_loops(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
|
||||
fn check_mod_loops(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
|
||||
tcx.hir().visit_item_likes_in_module(
|
||||
module_def_id,
|
||||
&mut CheckLoopVisitor { sess: &tcx.sess, hir_map: tcx.hir(), cx: Normal },
|
||||
|
@ -3,7 +3,7 @@
|
||||
use rustc_ast::InlineAsmOptions;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_hir::def_id::{LocalDefId, LocalModDefId};
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
use rustc_hir::{ExprKind, InlineAsmOperand, StmtKind};
|
||||
use rustc_middle::query::Providers;
|
||||
@ -23,7 +23,7 @@ pub(crate) fn provide(providers: &mut Providers) {
|
||||
*providers = Providers { check_mod_naked_functions, ..*providers };
|
||||
}
|
||||
|
||||
fn check_mod_naked_functions(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
|
||||
fn check_mod_naked_functions(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
|
||||
let items = tcx.hir_module_items(module_def_id);
|
||||
for def_id in items.definitions() {
|
||||
if !matches!(tcx.def_kind(def_id), DefKind::Fn | DefKind::AssocFn) {
|
||||
|
@ -9,7 +9,7 @@ use rustc_attr::{
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
|
||||
use rustc_hir::def_id::{LocalDefId, LocalModDefId, CRATE_DEF_ID};
|
||||
use rustc_hir::hir_id::CRATE_HIR_ID;
|
||||
use rustc_hir::intravisit::{self, Visitor};
|
||||
use rustc_hir::{FieldDef, Item, ItemKind, TraitRef, Ty, TyKind, Variant};
|
||||
@ -682,7 +682,7 @@ fn stability_index(tcx: TyCtxt<'_>, (): ()) -> Index {
|
||||
|
||||
/// Cross-references the feature names of unstable APIs with enabled
|
||||
/// features and possibly prints errors.
|
||||
fn check_mod_unstable_api_usage(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
|
||||
fn check_mod_unstable_api_usage(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
|
||||
tcx.hir().visit_item_likes_in_module(module_def_id, &mut Checker { tcx });
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,7 @@ use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
|
||||
use rustc_fluent_macro::fluent_messages;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
|
||||
use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId, CRATE_DEF_ID};
|
||||
use rustc_hir::intravisit::{self, Visitor};
|
||||
use rustc_hir::{AssocItemKind, ForeignItemKind, HirIdSet, ItemId, Node, PatKind};
|
||||
use rustc_middle::bug;
|
||||
@ -382,8 +382,9 @@ impl VisibilityLike for EffectiveVisibility {
|
||||
) -> Self {
|
||||
let effective_vis =
|
||||
find.effective_visibilities.effective_vis(def_id).copied().unwrap_or_else(|| {
|
||||
let private_vis =
|
||||
ty::Visibility::Restricted(find.tcx.parent_module_from_def_id(def_id));
|
||||
let private_vis = ty::Visibility::Restricted(
|
||||
find.tcx.parent_module_from_def_id(def_id).to_local_def_id(),
|
||||
);
|
||||
EffectiveVisibility::from_vis(private_vis)
|
||||
});
|
||||
|
||||
@ -412,7 +413,7 @@ struct EmbargoVisitor<'tcx> {
|
||||
/// pub macro m() {
|
||||
/// n::p::f()
|
||||
/// }
|
||||
macro_reachable: FxHashSet<(LocalDefId, LocalDefId)>,
|
||||
macro_reachable: FxHashSet<(LocalModDefId, LocalModDefId)>,
|
||||
/// Preliminary pass for marking all underlying types of `impl Trait`s as reachable.
|
||||
impl_trait_pass: bool,
|
||||
/// Has something changed in the level map?
|
||||
@ -449,7 +450,9 @@ impl<'tcx> EmbargoVisitor<'tcx> {
|
||||
max_vis: Option<ty::Visibility>,
|
||||
level: Level,
|
||||
) {
|
||||
let private_vis = ty::Visibility::Restricted(self.tcx.parent_module_from_def_id(def_id));
|
||||
// FIXME(typed_def_id): Make `Visibility::Restricted` use a `LocalModDefId` by default.
|
||||
let private_vis =
|
||||
ty::Visibility::Restricted(self.tcx.parent_module_from_def_id(def_id).into());
|
||||
if max_vis != Some(private_vis) {
|
||||
self.changed |= self.effective_visibilities.update(
|
||||
def_id,
|
||||
@ -508,6 +511,8 @@ impl<'tcx> EmbargoVisitor<'tcx> {
|
||||
// The macro's parent doesn't correspond to a `mod`, return early (#63164, #65252).
|
||||
return;
|
||||
}
|
||||
// FIXME(typed_def_id): Introduce checked constructors that check def_kind.
|
||||
let macro_module_def_id = LocalModDefId::new_unchecked(macro_module_def_id);
|
||||
|
||||
if self.effective_visibilities.public_at_level(local_def_id).is_none() {
|
||||
return;
|
||||
@ -519,10 +524,10 @@ impl<'tcx> EmbargoVisitor<'tcx> {
|
||||
loop {
|
||||
let changed_reachability =
|
||||
self.update_macro_reachable(module_def_id, macro_module_def_id, macro_ev);
|
||||
if changed_reachability || module_def_id == CRATE_DEF_ID {
|
||||
if changed_reachability || module_def_id == LocalModDefId::CRATE_DEF_ID {
|
||||
break;
|
||||
}
|
||||
module_def_id = self.tcx.local_parent(module_def_id);
|
||||
module_def_id = LocalModDefId::new_unchecked(self.tcx.local_parent(module_def_id));
|
||||
}
|
||||
}
|
||||
|
||||
@ -530,8 +535,8 @@ impl<'tcx> EmbargoVisitor<'tcx> {
|
||||
/// module. Returns `true` if the level has changed.
|
||||
fn update_macro_reachable(
|
||||
&mut self,
|
||||
module_def_id: LocalDefId,
|
||||
defining_mod: LocalDefId,
|
||||
module_def_id: LocalModDefId,
|
||||
defining_mod: LocalModDefId,
|
||||
macro_ev: EffectiveVisibility,
|
||||
) -> bool {
|
||||
if self.macro_reachable.insert((module_def_id, defining_mod)) {
|
||||
@ -544,8 +549,8 @@ impl<'tcx> EmbargoVisitor<'tcx> {
|
||||
|
||||
fn update_macro_reachable_mod(
|
||||
&mut self,
|
||||
module_def_id: LocalDefId,
|
||||
defining_mod: LocalDefId,
|
||||
module_def_id: LocalModDefId,
|
||||
defining_mod: LocalModDefId,
|
||||
macro_ev: EffectiveVisibility,
|
||||
) {
|
||||
let module = self.tcx.hir().get_module(module_def_id).0;
|
||||
@ -560,7 +565,7 @@ impl<'tcx> EmbargoVisitor<'tcx> {
|
||||
macro_ev,
|
||||
);
|
||||
}
|
||||
for child in self.tcx.module_children_local(module_def_id) {
|
||||
for child in self.tcx.module_children_local(module_def_id.to_local_def_id()) {
|
||||
// FIXME: Use module children for the logic above too.
|
||||
if !child.reexport_chain.is_empty()
|
||||
&& child.vis.is_accessible_from(defining_mod, self.tcx)
|
||||
@ -577,7 +582,7 @@ impl<'tcx> EmbargoVisitor<'tcx> {
|
||||
def_id: LocalDefId,
|
||||
def_kind: DefKind,
|
||||
vis: ty::Visibility,
|
||||
module: LocalDefId,
|
||||
module: LocalModDefId,
|
||||
macro_ev: EffectiveVisibility,
|
||||
) {
|
||||
self.update(def_id, macro_ev, Level::Reachable);
|
||||
@ -608,7 +613,11 @@ impl<'tcx> EmbargoVisitor<'tcx> {
|
||||
// the module, however may be reachable.
|
||||
DefKind::Mod => {
|
||||
if vis.is_accessible_from(module, self.tcx) {
|
||||
self.update_macro_reachable(def_id, module, macro_ev);
|
||||
self.update_macro_reachable(
|
||||
LocalModDefId::new_unchecked(def_id),
|
||||
module,
|
||||
macro_ev,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -892,7 +901,7 @@ fn vis_to_string<'tcx>(def_id: LocalDefId, vis: ty::Visibility, tcx: TyCtxt<'tcx
|
||||
ty::Visibility::Restricted(restricted_id) => {
|
||||
if restricted_id.is_top_level_module() {
|
||||
"pub(crate)".to_string()
|
||||
} else if restricted_id == tcx.parent_module_from_def_id(def_id) {
|
||||
} else if restricted_id == tcx.parent_module_from_def_id(def_id).to_local_def_id() {
|
||||
"pub(self)".to_string()
|
||||
} else {
|
||||
format!("pub({})", tcx.item_name(restricted_id.to_def_id()))
|
||||
@ -1800,7 +1809,7 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> {
|
||||
let vis_descr = match vis {
|
||||
ty::Visibility::Public => "public",
|
||||
ty::Visibility::Restricted(vis_def_id) => {
|
||||
if vis_def_id == self.tcx.parent_module(hir_id) {
|
||||
if vis_def_id == self.tcx.parent_module(hir_id).to_local_def_id() {
|
||||
"private"
|
||||
} else if vis_def_id.is_top_level_module() {
|
||||
"crate-private"
|
||||
@ -2196,7 +2205,7 @@ fn local_visibility(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Visibility {
|
||||
kind: hir::ItemKind::Use(_, hir::UseKind::ListStem)
|
||||
| hir::ItemKind::OpaqueTy(..),
|
||||
..
|
||||
}) => ty::Visibility::Restricted(tcx.parent_module(hir_id)),
|
||||
}) => ty::Visibility::Restricted(tcx.parent_module(hir_id).to_local_def_id()),
|
||||
// Visibilities of trait impl items are inherited from their traits
|
||||
// and are not filled in resolve.
|
||||
Node::ImplItem(impl_item) => {
|
||||
@ -2224,18 +2233,25 @@ fn local_visibility(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Visibility {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_mod_privacy(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
|
||||
fn check_mod_privacy(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
|
||||
// Check privacy of names not checked in previous compilation stages.
|
||||
let mut visitor =
|
||||
NamePrivacyVisitor { tcx, maybe_typeck_results: None, current_item: module_def_id };
|
||||
let mut visitor = NamePrivacyVisitor {
|
||||
tcx,
|
||||
maybe_typeck_results: None,
|
||||
current_item: module_def_id.to_local_def_id(),
|
||||
};
|
||||
let (module, span, hir_id) = tcx.hir().get_module(module_def_id);
|
||||
|
||||
intravisit::walk_mod(&mut visitor, module, hir_id);
|
||||
|
||||
// Check privacy of explicitly written types and traits as well as
|
||||
// inferred types of expressions and patterns.
|
||||
let mut visitor =
|
||||
TypePrivacyVisitor { tcx, maybe_typeck_results: None, current_item: module_def_id, span };
|
||||
let mut visitor = TypePrivacyVisitor {
|
||||
tcx,
|
||||
maybe_typeck_results: None,
|
||||
current_item: module_def_id.to_local_def_id(),
|
||||
span,
|
||||
};
|
||||
intravisit::walk_mod(&mut visitor, module, hir_id);
|
||||
}
|
||||
|
||||
|
@ -28,10 +28,16 @@ impl CrateNum {
|
||||
CrateNum::from_usize(x)
|
||||
}
|
||||
|
||||
// FIXME(typed_def_id): Replace this with `as_mod_def_id`.
|
||||
#[inline]
|
||||
pub fn as_def_id(self) -> DefId {
|
||||
DefId { krate: self, index: CRATE_DEF_INDEX }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn as_mod_def_id(self) -> ModDefId {
|
||||
ModDefId::new_unchecked(DefId { krate: self, index: CRATE_DEF_INDEX })
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for CrateNum {
|
||||
@ -485,3 +491,92 @@ impl<CTX: HashStableContext> ToStableHashKey<CTX> for CrateNum {
|
||||
self.as_def_id().to_stable_hash_key(hcx)
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! typed_def_id {
|
||||
($Name:ident, $LocalName:ident) => {
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Encodable, Decodable, HashStable_Generic)]
|
||||
pub struct $Name(DefId);
|
||||
|
||||
impl $Name {
|
||||
pub const fn new_unchecked(def_id: DefId) -> Self {
|
||||
Self(def_id)
|
||||
}
|
||||
|
||||
pub fn to_def_id(self) -> DefId {
|
||||
self.into()
|
||||
}
|
||||
|
||||
pub fn is_local(self) -> bool {
|
||||
self.0.is_local()
|
||||
}
|
||||
|
||||
pub fn as_local(self) -> Option<$LocalName> {
|
||||
self.0.as_local().map($LocalName::new_unchecked)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<$LocalName> for $Name {
|
||||
fn from(local: $LocalName) -> Self {
|
||||
Self(local.0.to_def_id())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<$Name> for DefId {
|
||||
fn from(typed: $Name) -> Self {
|
||||
typed.0
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Encodable, Decodable, HashStable_Generic)]
|
||||
pub struct $LocalName(LocalDefId);
|
||||
|
||||
impl !Ord for $LocalName {}
|
||||
impl !PartialOrd for $LocalName {}
|
||||
|
||||
impl $LocalName {
|
||||
pub const fn new_unchecked(def_id: LocalDefId) -> Self {
|
||||
Self(def_id)
|
||||
}
|
||||
|
||||
pub fn to_def_id(self) -> DefId {
|
||||
self.0.into()
|
||||
}
|
||||
|
||||
pub fn to_local_def_id(self) -> LocalDefId {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<$LocalName> for LocalDefId {
|
||||
fn from(typed: $LocalName) -> Self {
|
||||
typed.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<$LocalName> for DefId {
|
||||
fn from(typed: $LocalName) -> Self {
|
||||
typed.0.into()
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// N.B.: when adding new typed `DefId`s update the corresponding trait impls in
|
||||
// `rustc_middle::dep_graph::def_node` for `DepNodeParams`.
|
||||
typed_def_id! { ModDefId, LocalModDefId }
|
||||
|
||||
impl LocalModDefId {
|
||||
pub const CRATE_DEF_ID: Self = Self::new_unchecked(CRATE_DEF_ID);
|
||||
}
|
||||
|
||||
impl ModDefId {
|
||||
pub fn is_top_level_module(self) -> bool {
|
||||
self.0.is_top_level_module()
|
||||
}
|
||||
}
|
||||
|
||||
impl LocalModDefId {
|
||||
pub fn is_top_level_module(self) -> bool {
|
||||
self.0.is_top_level_module()
|
||||
}
|
||||
}
|
||||
|
@ -338,7 +338,7 @@ impl LinkerFlavor {
|
||||
|| stem == "clang++"
|
||||
|| stem.ends_with("-clang++")
|
||||
{
|
||||
(Some(Cc::Yes), None)
|
||||
(Some(Cc::Yes), Some(Lld::No))
|
||||
} else if stem == "wasm-ld"
|
||||
|| stem.ends_with("-wasm-ld")
|
||||
|| stem == "ld.lld"
|
||||
|
@ -281,23 +281,27 @@ pub(super) trait GoalKind<'tcx>:
|
||||
) -> QueryResult<'tcx>;
|
||||
|
||||
/// Consider (possibly several) candidates to upcast or unsize a type to another
|
||||
/// type.
|
||||
///
|
||||
/// The most common forms of unsizing are array to slice, and concrete (Sized)
|
||||
/// type into a `dyn Trait`. ADTs and Tuples can also have their final field
|
||||
/// unsized if it's generic.
|
||||
///
|
||||
/// `dyn Trait1` can be unsized to `dyn Trait2` if they are the same trait, or
|
||||
/// if `Trait2` is a (transitive) supertrait of `Trait2`.
|
||||
/// type, excluding the coercion of a sized type into a `dyn Trait`.
|
||||
///
|
||||
/// We return the `BuiltinImplSource` for each candidate as it is needed
|
||||
/// for unsize coercion in hir typeck and because it is difficult to
|
||||
/// otherwise recompute this for codegen. This is a bit of a mess but the
|
||||
/// easiest way to maintain the existing behavior for now.
|
||||
fn consider_builtin_unsize_candidates(
|
||||
fn consider_structural_builtin_unsize_candidates(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Vec<(CanonicalResponse<'tcx>, BuiltinImplSource)>;
|
||||
|
||||
/// Consider the `Unsize` candidate corresponding to coercing a sized type
|
||||
/// into a `dyn Trait`.
|
||||
///
|
||||
/// This is computed separately from the rest of the `Unsize` candidates
|
||||
/// since it is only done once per self type, and not once per
|
||||
/// *normalization step* (in `assemble_candidates_via_self_ty`).
|
||||
fn consider_unsize_to_dyn_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> QueryResult<'tcx>;
|
||||
}
|
||||
|
||||
impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||
@ -312,6 +316,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||
|
||||
let mut candidates = self.assemble_candidates_via_self_ty(goal, 0);
|
||||
|
||||
self.assemble_unsize_to_dyn_candidate(goal, &mut candidates);
|
||||
|
||||
self.assemble_blanket_impl_candidates(goal, &mut candidates);
|
||||
|
||||
self.assemble_param_env_candidates(goal, &mut candidates);
|
||||
@ -530,6 +536,23 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn assemble_unsize_to_dyn_candidate<G: GoalKind<'tcx>>(
|
||||
&mut self,
|
||||
goal: Goal<'tcx, G>,
|
||||
candidates: &mut Vec<Candidate<'tcx>>,
|
||||
) {
|
||||
let tcx = self.tcx();
|
||||
if tcx.lang_items().unsize_trait() == Some(goal.predicate.trait_def_id(tcx)) {
|
||||
match G::consider_unsize_to_dyn_candidate(self, goal) {
|
||||
Ok(result) => candidates.push(Candidate {
|
||||
source: CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
|
||||
result,
|
||||
}),
|
||||
Err(NoSolution) => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn assemble_blanket_impl_candidates<G: GoalKind<'tcx>>(
|
||||
&mut self,
|
||||
goal: Goal<'tcx, G>,
|
||||
@ -610,7 +633,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||
// There may be multiple unsize candidates for a trait with several supertraits:
|
||||
// `trait Foo: Bar<A> + Bar<B>` and `dyn Foo: Unsize<dyn Bar<_>>`
|
||||
if lang_items.unsize_trait() == Some(trait_def_id) {
|
||||
for (result, source) in G::consider_builtin_unsize_candidates(self, goal) {
|
||||
for (result, source) in G::consider_structural_builtin_unsize_candidates(self, goal) {
|
||||
candidates.push(Candidate { source: CandidateSource::BuiltinImpl(source), result });
|
||||
}
|
||||
}
|
||||
@ -826,6 +849,11 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||
ty::Dynamic(bounds, ..) => bounds,
|
||||
};
|
||||
|
||||
// Do not consider built-in object impls for non-object-safe types.
|
||||
if bounds.principal_def_id().is_some_and(|def_id| !tcx.check_is_object_safe(def_id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Consider all of the auto-trait and projection bounds, which don't
|
||||
// need to be recorded as a `BuiltinImplSource::Object` since they don't
|
||||
// really have a vtable base...
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::traits::specialization_graph;
|
||||
use crate::traits::{check_args_compatible, specialization_graph};
|
||||
|
||||
use super::assembly::{self, structural_traits};
|
||||
use super::EvalCtxt;
|
||||
@ -190,11 +190,8 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
|
||||
return ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS);
|
||||
};
|
||||
|
||||
if !assoc_def.item.defaultness(tcx).has_value() {
|
||||
let guar = tcx.sess.delay_span_bug(
|
||||
tcx.def_span(assoc_def.item.def_id),
|
||||
"missing value for assoc item in impl",
|
||||
);
|
||||
let error_response = |ecx: &mut EvalCtxt<'_, 'tcx>, reason| {
|
||||
let guar = tcx.sess.delay_span_bug(tcx.def_span(assoc_def.item.def_id), reason);
|
||||
let error_term = match assoc_def.item.kind {
|
||||
ty::AssocKind::Const => ty::Const::new_error(
|
||||
tcx,
|
||||
@ -208,7 +205,11 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
|
||||
};
|
||||
ecx.eq(goal.param_env, goal.predicate.term, error_term)
|
||||
.expect("expected goal term to be fully unconstrained");
|
||||
return ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
|
||||
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||
};
|
||||
|
||||
if !assoc_def.item.defaultness(tcx).has_value() {
|
||||
return error_response(ecx, "missing value for assoc item in impl");
|
||||
}
|
||||
|
||||
// Getting the right args here is complex, e.g. given:
|
||||
@ -233,6 +234,13 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
|
||||
assoc_def.defining_node,
|
||||
);
|
||||
|
||||
if !check_args_compatible(tcx, assoc_def.item, args) {
|
||||
return error_response(
|
||||
ecx,
|
||||
"associated item has mismatched generic item arguments",
|
||||
);
|
||||
}
|
||||
|
||||
// Finally we construct the actual value of the associated type.
|
||||
let term = match assoc_def.item.kind {
|
||||
ty::AssocKind::Type => tcx.type_of(assoc_def.item.def_id).map_bound(|ty| ty.into()),
|
||||
@ -497,7 +505,14 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
|
||||
)
|
||||
}
|
||||
|
||||
fn consider_builtin_unsize_candidates(
|
||||
fn consider_unsize_to_dyn_candidate(
|
||||
_ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> QueryResult<'tcx> {
|
||||
bug!("`Unsize` does not have an associated type: {:?}", goal)
|
||||
}
|
||||
|
||||
fn consider_structural_builtin_unsize_candidates(
|
||||
_ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Vec<(CanonicalResponse<'tcx>, BuiltinImplSource)> {
|
||||
|
@ -423,7 +423,55 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
||||
ecx.evaluate_added_goals_and_make_canonical_response(certainty)
|
||||
}
|
||||
|
||||
fn consider_builtin_unsize_candidates(
|
||||
fn consider_unsize_to_dyn_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> QueryResult<'tcx> {
|
||||
ecx.probe(|_| CandidateKind::UnsizeAssembly).enter(|ecx| {
|
||||
let a_ty = goal.predicate.self_ty();
|
||||
// We need to normalize the b_ty since it's destructured as a `dyn Trait`.
|
||||
let Some(b_ty) =
|
||||
ecx.try_normalize_ty(goal.param_env, goal.predicate.trait_ref.args.type_at(1))?
|
||||
else {
|
||||
return ecx.evaluate_added_goals_and_make_canonical_response(Certainty::OVERFLOW);
|
||||
};
|
||||
|
||||
let ty::Dynamic(b_data, b_region, ty::Dyn) = *b_ty.kind() else {
|
||||
return Err(NoSolution);
|
||||
};
|
||||
|
||||
let tcx = ecx.tcx();
|
||||
|
||||
// Can only unsize to an object-safe trait.
|
||||
if b_data.principal_def_id().is_some_and(|def_id| !tcx.check_is_object_safe(def_id)) {
|
||||
return Err(NoSolution);
|
||||
}
|
||||
|
||||
// Check that the type implements all of the predicates of the trait object.
|
||||
// (i.e. the principal, all of the associated types match, and any auto traits)
|
||||
ecx.add_goals(b_data.iter().map(|pred| goal.with(tcx, pred.with_self_ty(tcx, a_ty))));
|
||||
|
||||
// The type must be `Sized` to be unsized.
|
||||
if let Some(sized_def_id) = tcx.lang_items().sized_trait() {
|
||||
ecx.add_goal(goal.with(tcx, ty::TraitRef::new(tcx, sized_def_id, [a_ty])));
|
||||
} else {
|
||||
return Err(NoSolution);
|
||||
}
|
||||
|
||||
// The type must outlive the lifetime of the `dyn` we're unsizing into.
|
||||
ecx.add_goal(goal.with(tcx, ty::OutlivesPredicate(a_ty, b_region)));
|
||||
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||
})
|
||||
}
|
||||
|
||||
/// ```ignore (builtin impl example)
|
||||
/// trait Trait {
|
||||
/// fn foo(&self);
|
||||
/// }
|
||||
/// // results in the following builtin impl
|
||||
/// impl<'a, T: Trait + 'a> Unsize<dyn Trait + 'a> for T {}
|
||||
/// ```
|
||||
fn consider_structural_builtin_unsize_candidates(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Vec<(CanonicalResponse<'tcx>, BuiltinImplSource)> {
|
||||
@ -468,11 +516,8 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
||||
goal, a_data, a_region, b_data, b_region,
|
||||
),
|
||||
|
||||
// `T` -> `dyn Trait` unsizing
|
||||
(_, &ty::Dynamic(b_data, b_region, ty::Dyn)) => result_to_single(
|
||||
ecx.consider_builtin_unsize_to_dyn(goal, b_data, b_region),
|
||||
BuiltinImplSource::Misc,
|
||||
),
|
||||
// `T` -> `dyn Trait` unsizing is handled separately in `consider_unsize_to_dyn_candidate`
|
||||
(_, &ty::Dynamic(..)) => vec![],
|
||||
|
||||
// `[T; N]` -> `[T]` unsizing
|
||||
(&ty::Array(a_elem_ty, ..), &ty::Slice(b_elem_ty)) => result_to_single(
|
||||
@ -552,16 +597,18 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||
self.walk_vtable(
|
||||
a_principal.with_self_ty(tcx, a_ty),
|
||||
|ecx, new_a_principal, _, vtable_vptr_slot| {
|
||||
if let Ok(resp) = ecx.consider_builtin_upcast_to_principal(
|
||||
goal,
|
||||
a_data,
|
||||
a_region,
|
||||
b_data,
|
||||
b_region,
|
||||
Some(new_a_principal.map_bound(|trait_ref| {
|
||||
ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref)
|
||||
})),
|
||||
) {
|
||||
if let Ok(resp) = ecx.probe_candidate("dyn upcast").enter(|ecx| {
|
||||
ecx.consider_builtin_upcast_to_principal(
|
||||
goal,
|
||||
a_data,
|
||||
a_region,
|
||||
b_data,
|
||||
b_region,
|
||||
Some(new_a_principal.map_bound(|trait_ref| {
|
||||
ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref)
|
||||
})),
|
||||
)
|
||||
}) {
|
||||
responses
|
||||
.push((resp, BuiltinImplSource::TraitUpcasting { vtable_vptr_slot }));
|
||||
}
|
||||
@ -572,43 +619,6 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||
responses
|
||||
}
|
||||
|
||||
/// ```ignore (builtin impl example)
|
||||
/// trait Trait {
|
||||
/// fn foo(&self);
|
||||
/// }
|
||||
/// // results in the following builtin impl
|
||||
/// impl<'a, T: Trait + 'a> Unsize<dyn Trait + 'a> for T {}
|
||||
/// ```
|
||||
fn consider_builtin_unsize_to_dyn(
|
||||
&mut self,
|
||||
goal: Goal<'tcx, (Ty<'tcx>, Ty<'tcx>)>,
|
||||
b_data: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
|
||||
b_region: ty::Region<'tcx>,
|
||||
) -> QueryResult<'tcx> {
|
||||
let tcx = self.tcx();
|
||||
let Goal { predicate: (a_ty, _b_ty), .. } = goal;
|
||||
|
||||
// Can only unsize to an object-safe trait
|
||||
if b_data.principal_def_id().is_some_and(|def_id| !tcx.check_is_object_safe(def_id)) {
|
||||
return Err(NoSolution);
|
||||
}
|
||||
|
||||
// Check that the type implements all of the predicates of the trait object.
|
||||
// (i.e. the principal, all of the associated types match, and any auto traits)
|
||||
self.add_goals(b_data.iter().map(|pred| goal.with(tcx, pred.with_self_ty(tcx, a_ty))));
|
||||
|
||||
// The type must be `Sized` to be unsized.
|
||||
if let Some(sized_def_id) = tcx.lang_items().sized_trait() {
|
||||
self.add_goal(goal.with(tcx, ty::TraitRef::new(tcx, sized_def_id, [a_ty])));
|
||||
} else {
|
||||
return Err(NoSolution);
|
||||
}
|
||||
|
||||
// The type must outlive the lifetime of the `dyn` we're unsizing into.
|
||||
self.add_goal(goal.with(tcx, ty::OutlivesPredicate(a_ty, b_region)));
|
||||
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||
}
|
||||
|
||||
fn consider_builtin_upcast_to_principal(
|
||||
&mut self,
|
||||
goal: Goal<'tcx, (Ty<'tcx>, Ty<'tcx>)>,
|
||||
|
@ -82,12 +82,12 @@ use crate::str;
|
||||
#[stable(feature = "core_c_str", since = "1.64.0")]
|
||||
#[rustc_has_incoherent_inherent_impls]
|
||||
#[lang = "CStr"]
|
||||
// FIXME:
|
||||
// `fn from` in `impl From<&CStr> for Box<CStr>` current implementation relies
|
||||
// on `CStr` being layout-compatible with `[u8]`.
|
||||
// When attribute privacy is implemented, `CStr` should be annotated as `#[repr(transparent)]`.
|
||||
// Anyway, `CStr` representation and layout are considered implementation detail, are
|
||||
// not documented and must not be relied upon.
|
||||
// However, `CStr` layout is considered an implementation detail and must not be relied upon. We
|
||||
// want `repr(transparent)` but we don't want it to show up in rustdoc, so we hide it under
|
||||
// `cfg(doc)`. This is an ad-hoc implementation of attribute privacy.
|
||||
#[cfg_attr(not(doc), repr(transparent))]
|
||||
pub struct CStr {
|
||||
// FIXME: this should not be represented with a DST slice but rather with
|
||||
// just a raw `c_char` along with some form of marker to make
|
||||
|
@ -110,12 +110,12 @@ impl crate::sealed::Sealed for OsString {}
|
||||
/// [conversions]: super#conversions
|
||||
#[cfg_attr(not(test), rustc_diagnostic_item = "OsStr")]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
// FIXME:
|
||||
// `OsStr::from_inner` current implementation relies
|
||||
// on `OsStr` being layout-compatible with `Slice`.
|
||||
// When attribute privacy is implemented, `OsStr` should be annotated as `#[repr(transparent)]`.
|
||||
// Anyway, `OsStr` representation and layout are considered implementation details, are
|
||||
// not documented and must not be relied upon.
|
||||
// However, `OsStr` layout is considered an implementation detail and must not be relied upon. We
|
||||
// want `repr(transparent)` but we don't want it to show up in rustdoc, so we hide it under
|
||||
// `cfg(doc)`. This is an ad-hoc implementation of attribute privacy.
|
||||
#[cfg_attr(not(doc), repr(transparent))]
|
||||
pub struct OsStr {
|
||||
inner: Slice,
|
||||
}
|
||||
|
@ -1158,12 +1158,12 @@ impl FusedIterator for Ancestors<'_> {}
|
||||
/// Which method works best depends on what kind of situation you're in.
|
||||
#[cfg_attr(not(test), rustc_diagnostic_item = "PathBuf")]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
// FIXME:
|
||||
// `PathBuf::as_mut_vec` current implementation relies
|
||||
// on `PathBuf` being layout-compatible with `Vec<u8>`.
|
||||
// When attribute privacy is implemented, `PathBuf` should be annotated as `#[repr(transparent)]`.
|
||||
// Anyway, `PathBuf` representation and layout are considered implementation detail, are
|
||||
// not documented and must not be relied upon.
|
||||
// However, `PathBuf` layout is considered an implementation detail and must not be relied upon. We
|
||||
// want `repr(transparent)` but we don't want it to show up in rustdoc, so we hide it under
|
||||
// `cfg(doc)`. This is an ad-hoc implementation of attribute privacy.
|
||||
#[cfg_attr(not(doc), repr(transparent))]
|
||||
pub struct PathBuf {
|
||||
inner: OsString,
|
||||
}
|
||||
@ -1983,12 +1983,12 @@ impl AsRef<OsStr> for PathBuf {
|
||||
/// ```
|
||||
#[cfg_attr(not(test), rustc_diagnostic_item = "Path")]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
// FIXME:
|
||||
// `Path::new` current implementation relies
|
||||
// on `Path` being layout-compatible with `OsStr`.
|
||||
// When attribute privacy is implemented, `Path` should be annotated as `#[repr(transparent)]`.
|
||||
// Anyway, `Path` representation and layout are considered implementation detail, are
|
||||
// not documented and must not be relied upon.
|
||||
// However, `Path` layout is considered an implementation detail and must not be relied upon. We
|
||||
// want `repr(transparent)` but we don't want it to show up in rustdoc, so we hide it under
|
||||
// `cfg(doc)`. This is an ad-hoc implementation of attribute privacy.
|
||||
#[cfg_attr(not(doc), repr(transparent))]
|
||||
pub struct Path {
|
||||
inner: OsStr,
|
||||
}
|
||||
|
@ -16,14 +16,20 @@ pub struct WasiFd {
|
||||
fn iovec<'a>(a: &'a mut [IoSliceMut<'_>]) -> &'a [wasi::Iovec] {
|
||||
assert_eq!(mem::size_of::<IoSliceMut<'_>>(), mem::size_of::<wasi::Iovec>());
|
||||
assert_eq!(mem::align_of::<IoSliceMut<'_>>(), mem::align_of::<wasi::Iovec>());
|
||||
// SAFETY: `IoSliceMut` and `IoVec` have exactly the same memory layout
|
||||
// SAFETY: `IoSliceMut` and `IoVec` have exactly the same memory layout.
|
||||
// We decorate our `IoSliceMut` with `repr(transparent)` (see `io.rs`), and
|
||||
// `crate::io::IoSliceMut` is a `repr(transparent)` wrapper around our type, so this is
|
||||
// guaranteed.
|
||||
unsafe { mem::transmute(a) }
|
||||
}
|
||||
|
||||
fn ciovec<'a>(a: &'a [IoSlice<'_>]) -> &'a [wasi::Ciovec] {
|
||||
assert_eq!(mem::size_of::<IoSlice<'_>>(), mem::size_of::<wasi::Ciovec>());
|
||||
assert_eq!(mem::align_of::<IoSlice<'_>>(), mem::align_of::<wasi::Ciovec>());
|
||||
// SAFETY: `IoSlice` and `CIoVec` have exactly the same memory layout
|
||||
// SAFETY: `IoSlice` and `CIoVec` have exactly the same memory layout.
|
||||
// We decorate our `IoSlice` with `repr(transparent)` (see `io.rs`), and
|
||||
// `crate::io::IoSlice` is a `repr(transparent)` wrapper around our type, so this is
|
||||
// guaranteed.
|
||||
unsafe { mem::transmute(a) }
|
||||
}
|
||||
|
||||
|
@ -459,6 +459,7 @@ impl Wtf8Buf {
|
||||
/// Converts this `Wtf8Buf` into a boxed `Wtf8`.
|
||||
#[inline]
|
||||
pub fn into_box(self) -> Box<Wtf8> {
|
||||
// SAFETY: relies on `Wtf8` being `repr(transparent)`.
|
||||
unsafe { mem::transmute(self.bytes.into_boxed_slice()) }
|
||||
}
|
||||
|
||||
@ -511,6 +512,7 @@ impl Extend<CodePoint> for Wtf8Buf {
|
||||
/// Similar to `&str`, but can additionally contain surrogate code points
|
||||
/// if they’re not in a surrogate pair.
|
||||
#[derive(Eq, Ord, PartialEq, PartialOrd)]
|
||||
#[repr(transparent)]
|
||||
pub struct Wtf8 {
|
||||
bytes: [u8],
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ use rustc_ast as ast;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::def_id::{DefId, DefIdSet, LocalDefId};
|
||||
use rustc_hir::def_id::{DefId, DefIdSet, LocalModDefId};
|
||||
use rustc_hir::Mutability;
|
||||
use rustc_metadata::creader::{CStore, LoadedMacro};
|
||||
use rustc_middle::ty::fast_reject::SimplifiedType;
|
||||
@ -138,7 +138,7 @@ pub(crate) fn try_inline(
|
||||
pub(crate) fn try_inline_glob(
|
||||
cx: &mut DocContext<'_>,
|
||||
res: Res,
|
||||
current_mod: LocalDefId,
|
||||
current_mod: LocalModDefId,
|
||||
visited: &mut DefIdSet,
|
||||
inlined_names: &mut FxHashSet<(ItemType, Symbol)>,
|
||||
import: &hir::Item<'_>,
|
||||
@ -154,7 +154,7 @@ pub(crate) fn try_inline_glob(
|
||||
// reexported by the glob, e.g. because they are shadowed by something else.
|
||||
let reexports = cx
|
||||
.tcx
|
||||
.module_children_local(current_mod)
|
||||
.module_children_local(current_mod.to_local_def_id())
|
||||
.iter()
|
||||
.filter(|child| !child.reexport_chain.is_empty())
|
||||
.filter_map(|child| child.res.opt_def_id())
|
||||
|
@ -1551,7 +1551,7 @@ fn first_non_private<'tcx>(
|
||||
}
|
||||
[parent, leaf] if parent.ident.name == kw::Super => {
|
||||
let parent_mod = cx.tcx.parent_module(hir_id);
|
||||
if let Some(super_parent) = cx.tcx.opt_local_parent(parent_mod) {
|
||||
if let Some(super_parent) = cx.tcx.opt_local_parent(parent_mod.to_local_def_id()) {
|
||||
(super_parent, leaf.ident)
|
||||
} else {
|
||||
// If we can't find the parent of the parent, then the parent is already the crate.
|
||||
@ -2828,7 +2828,7 @@ fn clean_use_statement_inner<'tcx>(
|
||||
// The parent of the module in which this import resides. This
|
||||
// is the same as `current_mod` if that's already the top
|
||||
// level module.
|
||||
let parent_mod = cx.tcx.parent_module_from_def_id(current_mod);
|
||||
let parent_mod = cx.tcx.parent_module_from_def_id(current_mod.to_local_def_id());
|
||||
|
||||
// This checks if the import can be seen from a higher level module.
|
||||
// In other words, it checks if the visibility is the equivalent of
|
||||
|
@ -83,7 +83,7 @@ use rustc_ast::Attribute;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::unhash::UnhashMap;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
|
||||
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalModDefId, LOCAL_CRATE};
|
||||
use rustc_hir::hir_id::{HirIdMap, HirIdSet};
|
||||
use rustc_hir::intravisit::{walk_expr, FnKind, Visitor};
|
||||
use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk};
|
||||
@ -2370,11 +2370,11 @@ pub fn is_hir_ty_cfg_dependant(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
static TEST_ITEM_NAMES_CACHE: OnceLock<Mutex<FxHashMap<LocalDefId, Vec<Symbol>>>> = OnceLock::new();
|
||||
static TEST_ITEM_NAMES_CACHE: OnceLock<Mutex<FxHashMap<LocalModDefId, Vec<Symbol>>>> = OnceLock::new();
|
||||
|
||||
fn with_test_item_names(tcx: TyCtxt<'_>, module: LocalDefId, f: impl Fn(&[Symbol]) -> bool) -> bool {
|
||||
fn with_test_item_names(tcx: TyCtxt<'_>, module: LocalModDefId, f: impl Fn(&[Symbol]) -> bool) -> bool {
|
||||
let cache = TEST_ITEM_NAMES_CACHE.get_or_init(|| Mutex::new(FxHashMap::default()));
|
||||
let mut map: MutexGuard<'_, FxHashMap<LocalDefId, Vec<Symbol>>> = cache.lock().unwrap();
|
||||
let mut map: MutexGuard<'_, FxHashMap<LocalModDefId, Vec<Symbol>>> = cache.lock().unwrap();
|
||||
let value = map.entry(module);
|
||||
match value {
|
||||
Entry::Occupied(entry) => f(entry.get()),
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0049]: type `B` has 1 type parameter but its trait declaration has 0 type parameters
|
||||
--> $DIR/issue-102114.rs:11:12
|
||||
--> $DIR/issue-102114.rs:14:12
|
||||
|
|
||||
LL | type B<'b>;
|
||||
| -- expected 0 type parameters
|
12
tests/ui/generic-associated-types/issue-102114.next.stderr
Normal file
12
tests/ui/generic-associated-types/issue-102114.next.stderr
Normal file
@ -0,0 +1,12 @@
|
||||
error[E0049]: type `B` has 1 type parameter but its trait declaration has 0 type parameters
|
||||
--> $DIR/issue-102114.rs:14:12
|
||||
|
|
||||
LL | type B<'b>;
|
||||
| -- expected 0 type parameters
|
||||
...
|
||||
LL | type B<T> = Wrapper<T>;
|
||||
| ^ found 1 type parameter
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0049`.
|
@ -1,3 +1,6 @@
|
||||
// revisions: current next
|
||||
//[next] compile-flags: -Ztrait-solver=next
|
||||
|
||||
trait A {
|
||||
type B<'b>;
|
||||
fn a() -> Self::B<'static>;
|
||||
|
@ -17,7 +17,6 @@ trait Yay<AdditionalValue> {
|
||||
|
||||
impl<'a> Yay<&'a ()> for () {
|
||||
type InnerStream<'s> = impl Stream<Item = i32> + 's;
|
||||
//^ ERROR does not fulfill the required lifetime
|
||||
fn foo<'s>() -> Self::InnerStream<'s> {
|
||||
()
|
||||
}
|
||||
|
@ -13,7 +13,6 @@ struct Foo<'a>(&'a mut ());
|
||||
|
||||
impl Foo<'_> {
|
||||
type Fut<'a> = impl Future<Output = ()>;
|
||||
//^ ERROR: the type `&mut ()` does not fulfill the required lifetime
|
||||
|
||||
fn make_fut<'a>(&'a self) -> Self::Fut<'a> {
|
||||
async { () }
|
||||
|
@ -1,18 +1,18 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-90014-tait.rs:19:9
|
||||
--> $DIR/issue-90014-tait.rs:18:9
|
||||
|
|
||||
LL | type Fut<'a> = impl Future<Output = ()>;
|
||||
| ------------------------ the expected future
|
||||
...
|
||||
LL |
|
||||
LL | fn make_fut<'a>(&'a self) -> Self::Fut<'a> {
|
||||
| ------------- expected `Foo<'_>::Fut<'a>` because of return type
|
||||
LL | async { () }
|
||||
| ^^^^^^^^^^^^ expected future, found `async` block
|
||||
|
|
||||
= note: expected opaque type `Foo<'_>::Fut<'a>`
|
||||
found `async` block `[async block@$DIR/issue-90014-tait.rs:19:9: 19:21]`
|
||||
found `async` block `[async block@$DIR/issue-90014-tait.rs:18:9: 18:21]`
|
||||
note: this item must have the opaque type in its signature in order to be able to register hidden types
|
||||
--> $DIR/issue-90014-tait.rs:18:8
|
||||
--> $DIR/issue-90014-tait.rs:17:8
|
||||
|
|
||||
LL | fn make_fut<'a>(&'a self) -> Self::Fut<'a> {
|
||||
| ^^^^^^^^
|
||||
|
@ -8,7 +8,6 @@ extern crate internal_unstable;
|
||||
|
||||
struct Baz {
|
||||
#[allow_internal_unstable]
|
||||
//^ WARN `#[allow_internal_unstable]` is ignored on struct fields and match arms
|
||||
baz: u8,
|
||||
}
|
||||
|
||||
@ -50,7 +49,6 @@ fn main() {
|
||||
|
||||
match true {
|
||||
#[allow_internal_unstable]
|
||||
//^ WARN `#[allow_internal_unstable]` is ignored on struct fields and match arms
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0658]: use of unstable library feature 'function'
|
||||
--> $DIR/internal-unstable.rs:41:25
|
||||
--> $DIR/internal-unstable.rs:40:25
|
||||
|
|
||||
LL | pass_through_allow!(internal_unstable::unstable());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -7,7 +7,7 @@ LL | pass_through_allow!(internal_unstable::unstable());
|
||||
= help: add `#![feature(function)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: use of unstable library feature 'function'
|
||||
--> $DIR/internal-unstable.rs:43:27
|
||||
--> $DIR/internal-unstable.rs:42:27
|
||||
|
|
||||
LL | pass_through_noallow!(internal_unstable::unstable());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -15,7 +15,7 @@ LL | pass_through_noallow!(internal_unstable::unstable());
|
||||
= help: add `#![feature(function)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: use of unstable library feature 'function'
|
||||
--> $DIR/internal-unstable.rs:47:22
|
||||
--> $DIR/internal-unstable.rs:46:22
|
||||
|
|
||||
LL | println!("{:?}", internal_unstable::unstable());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -23,7 +23,7 @@ LL | println!("{:?}", internal_unstable::unstable());
|
||||
= help: add `#![feature(function)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: use of unstable library feature 'function'
|
||||
--> $DIR/internal-unstable.rs:49:10
|
||||
--> $DIR/internal-unstable.rs:48:10
|
||||
|
|
||||
LL | bar!(internal_unstable::unstable());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -31,7 +31,7 @@ LL | bar!(internal_unstable::unstable());
|
||||
= help: add `#![feature(function)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: use of unstable library feature 'function'
|
||||
--> $DIR/internal-unstable.rs:19:9
|
||||
--> $DIR/internal-unstable.rs:18:9
|
||||
|
|
||||
LL | internal_unstable::unstable();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
26
tests/ui/lint/unknown-lints/allow-in-other-module.rs
Normal file
26
tests/ui/lint/unknown-lints/allow-in-other-module.rs
Normal file
@ -0,0 +1,26 @@
|
||||
// check-pass
|
||||
|
||||
// Tests that the unknown_lints lint doesn't fire for an unknown lint loaded from a separate file.
|
||||
// The key part is that the stderr output should be empty.
|
||||
// Reported in https://github.com/rust-lang/rust/issues/84936
|
||||
// Fixed incidentally by https://github.com/rust-lang/rust/pull/97266
|
||||
|
||||
// This `allow` should apply to submodules, whether they are inline or loaded from a file.
|
||||
#![allow(unknown_lints)]
|
||||
#![allow(dead_code)]
|
||||
// no warning
|
||||
#![allow(not_a_real_lint)]
|
||||
|
||||
mod other;
|
||||
|
||||
// no warning
|
||||
#[allow(not_a_real_lint)]
|
||||
fn m() {}
|
||||
|
||||
mod mm {
|
||||
// no warning
|
||||
#[allow(not_a_real_lint)]
|
||||
fn m() {}
|
||||
}
|
||||
|
||||
fn main() {}
|
10
tests/ui/lint/unknown-lints/other.rs
Normal file
10
tests/ui/lint/unknown-lints/other.rs
Normal file
@ -0,0 +1,10 @@
|
||||
// ignore-test
|
||||
|
||||
// Companion to allow-in-other-module.rs
|
||||
|
||||
// This should not warn.
|
||||
#![allow(not_a_real_lint)]
|
||||
|
||||
// This should not warn, either.
|
||||
#[allow(not_a_real_lint)]
|
||||
fn m() {}
|
@ -6,9 +6,13 @@ pub enum ErrorHandled {
|
||||
impl ErrorHandled {
|
||||
pub fn assert_reported(self) {
|
||||
match self {
|
||||
//~^ NOTE this delimiter might not be properly closed...
|
||||
ErrorHandled::Reported => {}}
|
||||
//^~ ERROR block is empty, you might have not meant to close it
|
||||
//~^ NOTE block is empty, you might have not meant to close it
|
||||
//~| NOTE as it matches this but it has different indentation
|
||||
ErrorHandled::TooGeneric => panic!(),
|
||||
}
|
||||
}
|
||||
} //~ ERROR unexpected closing delimiter: `}`
|
||||
}
|
||||
//~^ ERROR unexpected closing delimiter: `}`
|
||||
//~| NOTE unexpected closing delimiter
|
||||
|
@ -1,8 +1,9 @@
|
||||
error: unexpected closing delimiter: `}`
|
||||
--> $DIR/issue-70583-block-is-empty-2.rs:14:1
|
||||
--> $DIR/issue-70583-block-is-empty-2.rs:16:1
|
||||
|
|
||||
LL | match self {
|
||||
| - this delimiter might not be properly closed...
|
||||
LL |
|
||||
LL | ErrorHandled::Reported => {}}
|
||||
| --- ...as it matches this but it has different indentation
|
||||
| |
|
||||
|
@ -1,5 +1,7 @@
|
||||
// Check that we can manually implement an object-unsafe trait for its trait object.
|
||||
|
||||
// revisions: current next
|
||||
//[next] compile-flags: -Ztrait-solver=next
|
||||
// run-pass
|
||||
|
||||
#![feature(object_safe_for_dispatch)]
|
||||
|
9
tests/ui/std/slice-from-array-issue-113238.rs
Normal file
9
tests/ui/std/slice-from-array-issue-113238.rs
Normal file
@ -0,0 +1,9 @@
|
||||
// check-pass
|
||||
|
||||
// This intends to use the unsizing coercion from array to slice, but it only
|
||||
// works if we resolve `<&[u8]>::from` as the reflexive `From<T> for T`. In
|
||||
// #113238, we found that gimli had added its own `From<EndianSlice> for &[u8]`
|
||||
// that affected all `std/backtrace` users.
|
||||
fn main() {
|
||||
let _ = <&[u8]>::from(&[]);
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
error[E0605]: non-primitive cast: `&dyn Foo` as `&dyn Bar<_>`
|
||||
--> $DIR/type-checking-test-1.rs:16:13
|
||||
--> $DIR/type-checking-test-1.rs:19:13
|
||||
|
|
||||
LL | let _ = x as &dyn Bar<_>; // Ambiguous
|
||||
| ^^^^^^^^^^^^^^^^ invalid cast
|
||||
@ -10,7 +10,7 @@ LL | let _ = &x as &dyn Bar<_>; // Ambiguous
|
||||
| +
|
||||
|
||||
error[E0277]: the trait bound `&dyn Foo: Bar<_>` is not satisfied
|
||||
--> $DIR/type-checking-test-1.rs:16:13
|
||||
--> $DIR/type-checking-test-1.rs:19:13
|
||||
|
|
||||
LL | let _ = x as &dyn Bar<_>; // Ambiguous
|
||||
| ^ the trait `Bar<_>` is not implemented for `&dyn Foo`
|
@ -0,0 +1,9 @@
|
||||
error[E0605]: non-primitive cast: `&dyn Foo` as `&dyn Bar<_>`
|
||||
--> $DIR/type-checking-test-1.rs:19:13
|
||||
|
|
||||
LL | let _ = x as &dyn Bar<_>; // Ambiguous
|
||||
| ^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0605`.
|
@ -1,3 +1,6 @@
|
||||
// revisions: current next
|
||||
//[next] compile-flags: -Ztrait-solver=next
|
||||
|
||||
#![feature(trait_upcasting)]
|
||||
|
||||
trait Foo: Bar<i32> + Bar<u32> {}
|
||||
@ -15,7 +18,7 @@ fn test_specific(x: &dyn Foo) {
|
||||
fn test_unknown_version(x: &dyn Foo) {
|
||||
let _ = x as &dyn Bar<_>; // Ambiguous
|
||||
//~^ ERROR non-primitive cast
|
||||
//~^^ ERROR the trait bound `&dyn Foo: Bar<_>` is not satisfied
|
||||
//[current]~^^ ERROR the trait bound `&dyn Foo: Bar<_>` is not satisfied
|
||||
}
|
||||
|
||||
fn test_infer_version(x: &dyn Foo) {
|
||||
|
@ -1,3 +1,5 @@
|
||||
// revisions: current next
|
||||
//[next] compile-flags: -Ztrait-solver=next
|
||||
// check-pass
|
||||
|
||||
trait Trait {}
|
||||
|
@ -14,7 +14,6 @@ trait Trait {
|
||||
|
||||
impl Trait for bool {
|
||||
fn a<T: Bound>(&self, _: T) {}
|
||||
//^~ This gets rejected but should be accepted
|
||||
fn b<T>(&self, _: T) where T: Bound {}
|
||||
fn c<T: Bound>(&self, _: T) {}
|
||||
fn d<T>(&self, _: T) where T: Bound {}
|
||||
|
Loading…
x
Reference in New Issue
Block a user