dont resolve defaults anymore, store foreign item defid instead of macro
This commit is contained in:
parent
5e5c724194
commit
e3cff18370
12 changed files with 188 additions and 100 deletions
|
|
@ -3813,6 +3813,19 @@ pub struct Fn {
|
|||
pub struct EiiImpl {
|
||||
pub node_id: NodeId,
|
||||
pub eii_macro_path: Path,
|
||||
/// This field is an implementation detail that prevents a lot of bugs.
|
||||
/// See <https://github.com/rust-lang/rust/issues/149981> for an example.
|
||||
///
|
||||
/// The problem is, that if we generate a declaration *together* with its default,
|
||||
/// we generate both a declaration and an implementation. The generated implementation
|
||||
/// uses the same mechanism to register itself as a user-defined implementation would,
|
||||
/// despite being invisible to users. What does happen is a name resolution step.
|
||||
/// The invisible default implementation has to find the declaration.
|
||||
/// Both are generated at the same time, so we can skip that name resolution step.
|
||||
///
|
||||
/// This field is that shortcut: we prefill the extern target to skip a name resolution step,
|
||||
/// making sure it never fails. It'd be awful UX if we fail name resolution in code invisible to the user.
|
||||
pub known_eii_macro_resolution: Option<EiiExternTarget>,
|
||||
pub impl_safety: Safety,
|
||||
pub span: Span,
|
||||
pub inner_span: Span,
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use rustc_abi::ExternAbi;
|
|||
use rustc_ast::visit::AssocCtxt;
|
||||
use rustc_ast::*;
|
||||
use rustc_errors::{E0570, ErrorGuaranteed, struct_span_code_err};
|
||||
use rustc_hir::attrs::{AttributeKind, EiiDecl};
|
||||
use rustc_hir::attrs::{AttributeKind, EiiDecl, EiiImplResolution};
|
||||
use rustc_hir::def::{DefKind, PerNS, Res};
|
||||
use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId};
|
||||
use rustc_hir::{
|
||||
|
|
@ -134,6 +134,55 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
}
|
||||
}
|
||||
|
||||
fn lower_eii_extern_target(
|
||||
&mut self,
|
||||
id: NodeId,
|
||||
EiiExternTarget { extern_item_path, impl_unsafe, span }: &EiiExternTarget,
|
||||
) -> Option<EiiDecl> {
|
||||
self.lower_path_simple_eii(id, extern_item_path).map(|did| EiiDecl {
|
||||
eii_extern_target: did,
|
||||
impl_unsafe: *impl_unsafe,
|
||||
span: self.lower_span(*span),
|
||||
})
|
||||
}
|
||||
|
||||
fn lower_eii_impl(
|
||||
&mut self,
|
||||
EiiImpl {
|
||||
node_id,
|
||||
eii_macro_path,
|
||||
impl_safety,
|
||||
span,
|
||||
inner_span,
|
||||
is_default,
|
||||
known_eii_macro_resolution,
|
||||
}: &EiiImpl,
|
||||
) -> hir::attrs::EiiImpl {
|
||||
let resolution = if let Some(target) = known_eii_macro_resolution
|
||||
&& let Some(decl) = self.lower_eii_extern_target(*node_id, target)
|
||||
{
|
||||
EiiImplResolution::Known(
|
||||
decl,
|
||||
// the expect is ok here since we always generate this path in the eii macro.
|
||||
eii_macro_path.segments.last().expect("at least one segment").ident.name,
|
||||
)
|
||||
} else if let Some(macro_did) = self.lower_path_simple_eii(*node_id, eii_macro_path) {
|
||||
EiiImplResolution::Macro(macro_did)
|
||||
} else {
|
||||
EiiImplResolution::Error(
|
||||
self.dcx().span_delayed_bug(*span, "eii never resolved without errors given"),
|
||||
)
|
||||
};
|
||||
|
||||
hir::attrs::EiiImpl {
|
||||
span: self.lower_span(*span),
|
||||
inner_span: self.lower_span(*inner_span),
|
||||
impl_marked_unsafe: self.lower_safety(*impl_safety, hir::Safety::Safe).is_unsafe(),
|
||||
is_default: *is_default,
|
||||
resolution,
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_extra_attrs_for_item_kind(
|
||||
&mut self,
|
||||
id: NodeId,
|
||||
|
|
@ -143,49 +192,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
ItemKind::Fn(box Fn { eii_impls, .. }) if eii_impls.is_empty() => Vec::new(),
|
||||
ItemKind::Fn(box Fn { eii_impls, .. }) => {
|
||||
vec![hir::Attribute::Parsed(AttributeKind::EiiImpls(
|
||||
eii_impls
|
||||
.iter()
|
||||
.flat_map(
|
||||
|EiiImpl {
|
||||
node_id,
|
||||
eii_macro_path,
|
||||
impl_safety,
|
||||
span,
|
||||
inner_span,
|
||||
is_default,
|
||||
}| {
|
||||
self.lower_path_simple_eii(*node_id, eii_macro_path).map(|did| {
|
||||
hir::attrs::EiiImpl {
|
||||
eii_macro: did,
|
||||
span: self.lower_span(*span),
|
||||
inner_span: self.lower_span(*inner_span),
|
||||
impl_marked_unsafe: self
|
||||
.lower_safety(*impl_safety, hir::Safety::Safe)
|
||||
.is_unsafe(),
|
||||
is_default: *is_default,
|
||||
}
|
||||
})
|
||||
},
|
||||
)
|
||||
.collect(),
|
||||
eii_impls.iter().map(|i| self.lower_eii_impl(i)).collect(),
|
||||
))]
|
||||
}
|
||||
ItemKind::MacroDef(
|
||||
_,
|
||||
MacroDef {
|
||||
eii_extern_target: Some(EiiExternTarget { extern_item_path, impl_unsafe, span }),
|
||||
..
|
||||
},
|
||||
) => self
|
||||
.lower_path_simple_eii(id, extern_item_path)
|
||||
.map(|did| {
|
||||
vec![hir::Attribute::Parsed(AttributeKind::EiiExternTarget(EiiDecl {
|
||||
eii_extern_target: did,
|
||||
impl_unsafe: *impl_unsafe,
|
||||
span: self.lower_span(*span),
|
||||
}))]
|
||||
})
|
||||
ItemKind::MacroDef(_, MacroDef { eii_extern_target: Some(target), .. }) => self
|
||||
.lower_eii_extern_target(id, target)
|
||||
.map(|decl| vec![hir::Attribute::Parsed(AttributeKind::EiiExternTarget(decl))])
|
||||
.unwrap_or_default(),
|
||||
|
||||
ItemKind::ExternCrate(..)
|
||||
| ItemKind::Use(..)
|
||||
| ItemKind::Static(..)
|
||||
|
|
|
|||
|
|
@ -116,6 +116,7 @@ fn eii_(
|
|||
macro_name,
|
||||
eii_attr_span,
|
||||
item_span,
|
||||
foreign_item_name,
|
||||
)))
|
||||
}
|
||||
|
||||
|
|
@ -192,6 +193,7 @@ fn generate_default_impl(
|
|||
macro_name: Ident,
|
||||
eii_attr_span: Span,
|
||||
item_span: Span,
|
||||
foreign_item_name: Ident,
|
||||
) -> ast::Item {
|
||||
// FIXME: re-add some original attrs
|
||||
let attrs = ThinVec::new();
|
||||
|
|
@ -208,6 +210,11 @@ fn generate_default_impl(
|
|||
},
|
||||
span: eii_attr_span,
|
||||
is_default: true,
|
||||
known_eii_macro_resolution: Some(ast::EiiExternTarget {
|
||||
extern_item_path: ast::Path::from_ident(foreign_item_name),
|
||||
impl_unsafe,
|
||||
span: item_span,
|
||||
}),
|
||||
});
|
||||
|
||||
ast::Item {
|
||||
|
|
@ -508,6 +515,7 @@ pub(crate) fn eii_shared_macro(
|
|||
impl_safety: meta_item.unsafety,
|
||||
span,
|
||||
is_default,
|
||||
known_eii_macro_resolution: None,
|
||||
});
|
||||
|
||||
vec![item]
|
||||
|
|
|
|||
|
|
@ -3,7 +3,9 @@ use std::str::FromStr;
|
|||
use rustc_abi::{Align, ExternAbi};
|
||||
use rustc_ast::expand::autodiff_attrs::{AutoDiffAttrs, DiffActivity, DiffMode};
|
||||
use rustc_ast::{LitKind, MetaItem, MetaItemInner, attr};
|
||||
use rustc_hir::attrs::{AttributeKind, InlineAttr, Linkage, RtsanSetting, UsedBy};
|
||||
use rustc_hir::attrs::{
|
||||
AttributeKind, EiiImplResolution, InlineAttr, Linkage, RtsanSetting, UsedBy,
|
||||
};
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId};
|
||||
use rustc_hir::{self as hir, Attribute, LangItem, find_attr, lang_items};
|
||||
|
|
@ -285,15 +287,22 @@ fn process_builtin_attrs(
|
|||
}
|
||||
AttributeKind::EiiImpls(impls) => {
|
||||
for i in impls {
|
||||
let Some(extern_item) = find_attr!(
|
||||
tcx.get_all_attrs(i.eii_macro),
|
||||
AttributeKind::EiiExternTarget(target) => target.eii_extern_target
|
||||
) else {
|
||||
tcx.dcx().span_delayed_bug(
|
||||
i.span,
|
||||
"resolved to something that's not an EII",
|
||||
);
|
||||
continue;
|
||||
let extern_item = match i.resolution {
|
||||
EiiImplResolution::Macro(def_id) => {
|
||||
let Some(extern_item) = find_attr!(
|
||||
tcx.get_all_attrs(def_id),
|
||||
AttributeKind::EiiExternTarget(target) => target.eii_extern_target
|
||||
) else {
|
||||
tcx.dcx().span_delayed_bug(
|
||||
i.span,
|
||||
"resolved to something that's not an EII",
|
||||
);
|
||||
continue;
|
||||
};
|
||||
extern_item
|
||||
}
|
||||
EiiImplResolution::Known(decl, _) => decl.eii_extern_target,
|
||||
EiiImplResolution::Error(_eg) => continue,
|
||||
};
|
||||
|
||||
// this is to prevent a bug where a single crate defines both the default and explicit implementation
|
||||
|
|
@ -307,7 +316,7 @@ fn process_builtin_attrs(
|
|||
// iterate over all implementations *in the current crate*
|
||||
// (this is ok since we generate codegen fn attrs in the local crate)
|
||||
// if any of them is *not default* then don't emit the alias.
|
||||
&& tcx.externally_implementable_items(LOCAL_CRATE).get(&i.eii_macro).expect("at least one").1.iter().any(|(_, imp)| !imp.is_default)
|
||||
&& tcx.externally_implementable_items(LOCAL_CRATE).get(&extern_item).expect("at least one").1.iter().any(|(_, imp)| !imp.is_default)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use rustc_error_messages::{DiagArgValue, IntoDiagArg};
|
|||
use rustc_macros::{Decodable, Encodable, HashStable_Generic, PrintAttribute};
|
||||
use rustc_span::def_id::DefId;
|
||||
use rustc_span::hygiene::Transparency;
|
||||
use rustc_span::{Ident, Span, Symbol};
|
||||
use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol};
|
||||
pub use rustc_target::spec::SanitizerSet;
|
||||
use thin_vec::ThinVec;
|
||||
|
||||
|
|
@ -19,9 +19,22 @@ use crate::attrs::pretty_printing::PrintAttribute;
|
|||
use crate::limit::Limit;
|
||||
use crate::{DefaultBodyStability, PartialConstStability, RustcVersion, Stability};
|
||||
|
||||
#[derive(Copy, Clone, Debug, HashStable_Generic, Encodable, Decodable, PrintAttribute)]
|
||||
pub enum EiiImplResolution {
|
||||
/// Usually, finding the extern item that an EII implementation implements means finding
|
||||
/// the defid of the associated attribute macro, and looking at *its* attributes to find
|
||||
/// what foreign item its associated with.
|
||||
Macro(DefId),
|
||||
/// Sometimes though, we already know statically and can skip some name resolution.
|
||||
/// Stored together with the eii's name for diagnostics.
|
||||
Known(EiiDecl, Symbol),
|
||||
/// For when resolution failed, but we want to continue compilation
|
||||
Error(ErrorGuaranteed),
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, HashStable_Generic, Encodable, Decodable, PrintAttribute)]
|
||||
pub struct EiiImpl {
|
||||
pub eii_macro: DefId,
|
||||
pub resolution: EiiImplResolution,
|
||||
pub impl_marked_unsafe: bool,
|
||||
pub span: Span,
|
||||
pub inner_span: Span,
|
||||
|
|
|
|||
|
|
@ -32,21 +32,21 @@ use crate::errors::{EiiWithGenerics, LifetimesOrBoundsMismatchOnEii};
|
|||
pub(crate) fn compare_eii_function_types<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
external_impl: LocalDefId,
|
||||
declaration: DefId,
|
||||
foreign_item: DefId,
|
||||
eii_name: Symbol,
|
||||
eii_attr_span: Span,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
check_is_structurally_compatible(tcx, external_impl, declaration, eii_name, eii_attr_span)?;
|
||||
check_is_structurally_compatible(tcx, external_impl, foreign_item, eii_name, eii_attr_span)?;
|
||||
|
||||
let external_impl_span = tcx.def_span(external_impl);
|
||||
let cause = ObligationCause::new(
|
||||
external_impl_span,
|
||||
external_impl,
|
||||
ObligationCauseCode::CompareEii { external_impl, declaration },
|
||||
ObligationCauseCode::CompareEii { external_impl, declaration: foreign_item },
|
||||
);
|
||||
|
||||
// FIXME(eii): even if we don't support generic functions, we should support explicit outlive bounds here
|
||||
let param_env = tcx.param_env(declaration);
|
||||
let param_env = tcx.param_env(foreign_item);
|
||||
|
||||
let infcx = &tcx.infer_ctxt().build(TypingMode::non_body_analysis());
|
||||
let ocx = ObligationCtxt::new_with_diagnostics(infcx);
|
||||
|
|
@ -62,7 +62,7 @@ pub(crate) fn compare_eii_function_types<'tcx>(
|
|||
let mut wf_tys = FxIndexSet::default();
|
||||
let norm_cause = ObligationCause::misc(external_impl_span, external_impl);
|
||||
|
||||
let declaration_sig = tcx.fn_sig(declaration).instantiate_identity();
|
||||
let declaration_sig = tcx.fn_sig(foreign_item).instantiate_identity();
|
||||
let declaration_sig = tcx.liberate_late_bound_regions(external_impl.into(), declaration_sig);
|
||||
debug!(?declaration_sig);
|
||||
|
||||
|
|
@ -103,7 +103,7 @@ pub(crate) fn compare_eii_function_types<'tcx>(
|
|||
cause,
|
||||
param_env,
|
||||
terr,
|
||||
(declaration, declaration_sig),
|
||||
(foreign_item, declaration_sig),
|
||||
(external_impl, external_impl_sig),
|
||||
eii_attr_span,
|
||||
eii_name,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use rustc_abi::{ExternAbi, ScalableElt};
|
|||
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
|
||||
use rustc_errors::codes::*;
|
||||
use rustc_errors::{Applicability, ErrorGuaranteed, pluralize, struct_span_code_err};
|
||||
use rustc_hir::attrs::{AttributeKind, EiiDecl, EiiImpl};
|
||||
use rustc_hir::attrs::{AttributeKind, EiiDecl, EiiImpl, EiiImplResolution};
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
|
|
@ -1196,25 +1196,28 @@ fn check_item_fn(
|
|||
fn check_eiis(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
||||
// does the function have an EiiImpl attribute? that contains the defid of a *macro*
|
||||
// that was used to mark the implementation. This is a two step process.
|
||||
for EiiImpl { eii_macro, span, .. } in
|
||||
for EiiImpl { resolution, span, .. } in
|
||||
find_attr!(tcx.get_all_attrs(def_id), AttributeKind::EiiImpls(impls) => impls)
|
||||
.into_iter()
|
||||
.flatten()
|
||||
{
|
||||
// we expect this macro to have the `EiiMacroFor` attribute, that points to a function
|
||||
// signature that we'd like to compare the function we're currently checking with
|
||||
if let Some(eii_extern_target) = find_attr!(tcx.get_all_attrs(*eii_macro), AttributeKind::EiiExternTarget(EiiDecl {eii_extern_target, ..}) => *eii_extern_target)
|
||||
{
|
||||
let _ = compare_eii_function_types(
|
||||
tcx,
|
||||
def_id,
|
||||
eii_extern_target,
|
||||
tcx.item_name(*eii_macro),
|
||||
*span,
|
||||
);
|
||||
} else {
|
||||
tcx.dcx().span_delayed_bug(*span, "resolved to something that's not an EII");
|
||||
}
|
||||
let (foreign_item, name) = match resolution {
|
||||
EiiImplResolution::Macro(def_id) => {
|
||||
// we expect this macro to have the `EiiMacroFor` attribute, that points to a function
|
||||
// signature that we'd like to compare the function we're currently checking with
|
||||
if let Some(foreign_item) = find_attr!(tcx.get_all_attrs(*def_id), AttributeKind::EiiExternTarget(EiiDecl {eii_extern_target: t, ..}) => *t)
|
||||
{
|
||||
(foreign_item, tcx.item_name(*def_id))
|
||||
} else {
|
||||
tcx.dcx().span_delayed_bug(*span, "resolved to something that's not an EII");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
EiiImplResolution::Known(decl, name) => (decl.eii_extern_target, *name),
|
||||
EiiImplResolution::Error(_eg) => continue,
|
||||
};
|
||||
|
||||
let _ = compare_eii_function_types(tcx, def_id, foreign_item, name, *span);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use rustc_data_structures::indexmap::map::Entry;
|
||||
use rustc_hir::attrs::{AttributeKind, EiiDecl, EiiImpl};
|
||||
use rustc_hir::attrs::{AttributeKind, EiiDecl, EiiImpl, EiiImplResolution};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::find_attr;
|
||||
use rustc_middle::query::LocalCrate;
|
||||
|
|
@ -10,7 +9,7 @@ use rustc_middle::ty::TyCtxt;
|
|||
pub(crate) type EiiMapEncodedKeyValue = (DefId, (EiiDecl, Vec<(DefId, EiiImpl)>));
|
||||
|
||||
pub(crate) type EiiMap = FxIndexMap<
|
||||
DefId, // the defid of the macro that declared the eii
|
||||
DefId, // the defid of the foreign item associated with the eii
|
||||
(
|
||||
// the corresponding declaration
|
||||
EiiDecl,
|
||||
|
|
@ -29,29 +28,34 @@ pub(crate) fn collect<'tcx>(tcx: TyCtxt<'tcx>, LocalCrate: LocalCrate) -> EiiMap
|
|||
for i in
|
||||
find_attr!(tcx.get_all_attrs(id), AttributeKind::EiiImpls(e) => e).into_iter().flatten()
|
||||
{
|
||||
let registered_impls = match eiis.entry(i.eii_macro) {
|
||||
Entry::Occupied(o) => &mut o.into_mut().1,
|
||||
Entry::Vacant(v) => {
|
||||
let decl = match i.resolution {
|
||||
EiiImplResolution::Macro(macro_defid) => {
|
||||
// find the decl for this one if it wasn't in yet (maybe it's from the local crate? not very useful but not illegal)
|
||||
let Some(decl) = find_attr!(tcx.get_all_attrs(i.eii_macro), AttributeKind::EiiExternTarget(d) => *d)
|
||||
let Some(decl) = find_attr!(tcx.get_all_attrs(macro_defid), AttributeKind::EiiExternTarget(d) => *d)
|
||||
else {
|
||||
// skip if it doesn't have eii_extern_target (if we resolved to another macro that's not an EII)
|
||||
tcx.dcx()
|
||||
.span_delayed_bug(i.span, "resolved to something that's not an EII");
|
||||
continue;
|
||||
};
|
||||
&mut v.insert((decl, Default::default())).1
|
||||
decl
|
||||
}
|
||||
EiiImplResolution::Known(decl, _) => decl,
|
||||
EiiImplResolution::Error(_eg) => continue,
|
||||
};
|
||||
|
||||
registered_impls.insert(id.into(), *i);
|
||||
// FIXME(eii) remove extern target from encoded decl
|
||||
eiis.entry(decl.eii_extern_target)
|
||||
.or_insert_with(|| (decl, Default::default()))
|
||||
.1
|
||||
.insert(id.into(), *i);
|
||||
}
|
||||
|
||||
// if we find a new declaration, add it to the list without a known implementation
|
||||
if let Some(decl) =
|
||||
find_attr!(tcx.get_all_attrs(id), AttributeKind::EiiExternTarget(d) => *d)
|
||||
{
|
||||
eiis.entry(id.into()).or_insert((decl, Default::default()));
|
||||
eiis.entry(decl.eii_extern_target).or_insert((decl, Default::default()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1657,9 +1657,14 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
|||
empty_proc_macro!(self);
|
||||
let externally_implementable_items = self.tcx.externally_implementable_items(LOCAL_CRATE);
|
||||
|
||||
self.lazy_array(externally_implementable_items.iter().map(|(decl_did, (decl, impls))| {
|
||||
(*decl_did, (decl.clone(), impls.iter().map(|(impl_did, i)| (*impl_did, *i)).collect()))
|
||||
}))
|
||||
self.lazy_array(externally_implementable_items.iter().map(
|
||||
|(foreign_item, (decl, impls))| {
|
||||
(
|
||||
*foreign_item,
|
||||
(decl.clone(), impls.iter().map(|(impl_did, i)| (*impl_did, *i)).collect()),
|
||||
)
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
#[instrument(level = "trace", skip(self))]
|
||||
|
|
|
|||
|
|
@ -21,8 +21,8 @@ use rustc_feature::{
|
|||
BuiltinAttribute,
|
||||
};
|
||||
use rustc_hir::attrs::{
|
||||
AttributeKind, DocAttribute, DocInline, EiiDecl, EiiImpl, InlineAttr, MirDialect, MirPhase,
|
||||
ReprAttr, SanitizerSet,
|
||||
AttributeKind, DocAttribute, DocInline, EiiDecl, EiiImpl, EiiImplResolution, InlineAttr,
|
||||
MirDialect, MirPhase, ReprAttr, SanitizerSet,
|
||||
};
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::LocalModDefId;
|
||||
|
|
@ -506,7 +506,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
}
|
||||
|
||||
fn check_eii_impl(&self, impls: &[EiiImpl], target: Target) {
|
||||
for EiiImpl { span, inner_span, eii_macro, impl_marked_unsafe, is_default: _ } in impls {
|
||||
for EiiImpl { span, inner_span, resolution, impl_marked_unsafe, is_default: _ } in impls {
|
||||
match target {
|
||||
Target::Fn => {}
|
||||
_ => {
|
||||
|
|
@ -514,7 +514,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
if find_attr!(self.tcx.get_all_attrs(*eii_macro), AttributeKind::EiiExternTarget(EiiDecl { impl_unsafe, .. }) if *impl_unsafe)
|
||||
if let EiiImplResolution::Macro(eii_macro) = resolution
|
||||
&& find_attr!(self.tcx.get_all_attrs(*eii_macro), AttributeKind::EiiExternTarget(EiiDecl { impl_unsafe, .. }) if *impl_unsafe)
|
||||
&& !impl_marked_unsafe
|
||||
{
|
||||
self.dcx().emit_err(errors::EiiImplRequiresUnsafe {
|
||||
|
|
@ -758,9 +759,14 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
if let Some(impls) = find_attr!(attrs, AttributeKind::EiiImpls(impls) => impls) {
|
||||
let sig = self.tcx.hir_node(hir_id).fn_sig().unwrap();
|
||||
for i in impls {
|
||||
let name = match i.resolution {
|
||||
EiiImplResolution::Macro(def_id) => self.tcx.item_name(def_id),
|
||||
EiiImplResolution::Known(_, name) => name,
|
||||
EiiImplResolution::Error(_eg) => continue,
|
||||
};
|
||||
self.dcx().emit_err(errors::EiiWithTrackCaller {
|
||||
attr_span,
|
||||
name: self.tcx.item_name(i.eii_macro),
|
||||
name,
|
||||
sig_span: sig.span,
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ pub(crate) fn check_externally_implementable_items<'tcx>(tcx: TyCtxt<'tcx>, ():
|
|||
}
|
||||
|
||||
// now we have all eiis! For each of them, choose one we want to actually generate.
|
||||
for (decl_did, FoundEii { decl, decl_crate, impls }) in eiis {
|
||||
for (foreign_item, FoundEii { decl, decl_crate, impls }) in eiis {
|
||||
let mut default_impls = Vec::new();
|
||||
let mut explicit_impls = Vec::new();
|
||||
|
||||
|
|
@ -97,7 +97,7 @@ pub(crate) fn check_externally_implementable_items<'tcx>(tcx: TyCtxt<'tcx>, ():
|
|||
// is instantly an error.
|
||||
if explicit_impls.len() > 1 {
|
||||
tcx.dcx().emit_err(DuplicateEiiImpls {
|
||||
name: tcx.item_name(decl_did),
|
||||
name: tcx.item_name(foreign_item),
|
||||
first_span: tcx.def_span(explicit_impls[0].0),
|
||||
first_crate: tcx.crate_name(explicit_impls[0].1),
|
||||
second_span: tcx.def_span(explicit_impls[1].0),
|
||||
|
|
@ -116,7 +116,7 @@ pub(crate) fn check_externally_implementable_items<'tcx>(tcx: TyCtxt<'tcx>, ():
|
|||
}
|
||||
|
||||
if default_impls.len() > 1 {
|
||||
let decl_span = tcx.def_ident_span(decl_did).unwrap();
|
||||
let decl_span = tcx.def_ident_span(foreign_item).unwrap();
|
||||
tcx.dcx().span_delayed_bug(decl_span, "multiple not supported right now");
|
||||
}
|
||||
|
||||
|
|
@ -139,7 +139,8 @@ pub(crate) fn check_externally_implementable_items<'tcx>(tcx: TyCtxt<'tcx>, ():
|
|||
tcx.dcx().emit_err(EiiWithoutImpl {
|
||||
current_crate_name: tcx.crate_name(LOCAL_CRATE),
|
||||
decl_crate_name: tcx.crate_name(decl_crate),
|
||||
name: tcx.item_name(decl_did),
|
||||
// FIXME: shouldn't call `item_name`
|
||||
name: tcx.item_name(foreign_item),
|
||||
span: decl.span,
|
||||
help: (),
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1069,8 +1069,20 @@ impl<'ast, 'ra, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'ra, 'tc
|
|||
debug!("(resolving function) entering function");
|
||||
|
||||
if let FnKind::Fn(_, _, f) = fn_kind {
|
||||
for EiiImpl { node_id, eii_macro_path, .. } in &f.eii_impls {
|
||||
self.smart_resolve_path(*node_id, &None, &eii_macro_path, PathSource::Macro);
|
||||
for EiiImpl { node_id, eii_macro_path, known_eii_macro_resolution, .. } in &f.eii_impls
|
||||
{
|
||||
// See docs on the `known_eii_macro_resolution` field:
|
||||
// if we already know the resolution statically, don't bother resolving it.
|
||||
if let Some(target) = known_eii_macro_resolution {
|
||||
self.smart_resolve_path(
|
||||
*node_id,
|
||||
&None,
|
||||
&target.extern_item_path,
|
||||
PathSource::Expr(None),
|
||||
);
|
||||
} else {
|
||||
self.smart_resolve_path(*node_id, &None, &eii_macro_path, PathSource::Macro);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue