diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 57765cc379a5..2c287045be7a 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -441,6 +441,8 @@ pub(crate) enum PathSource<'a, 'ast, 'ra> { TraitItem(Namespace, &'a PathSource<'a, 'ast, 'ra>), /// Paths in delegation item Delegation, + /// Paths in externally implementable item declarations. + ExternItemImpl, /// An arg in a `use<'a, N>` precise-capturing bound. PreciseCapturingArg(Namespace), /// Paths that end with `(..)`, for return type notation. @@ -465,6 +467,7 @@ fn namespace(self) -> Namespace { | PathSource::Pat | PathSource::TupleStruct(..) | PathSource::Delegation + | PathSource::ExternItemImpl | PathSource::ReturnTypeNotation => ValueNS, PathSource::TraitItem(ns, _) => ns, PathSource::PreciseCapturingArg(ns) => ns, @@ -484,6 +487,7 @@ fn defer_to_typeck(self) -> bool { | PathSource::TraitItem(..) | PathSource::DefineOpaques | PathSource::Delegation + | PathSource::ExternItemImpl | PathSource::PreciseCapturingArg(..) | PathSource::Macro | PathSource::Module => false, @@ -526,7 +530,9 @@ fn descr_expected(self) -> &'static str { }, _ => "value", }, - PathSource::ReturnTypeNotation | PathSource::Delegation => "function", + PathSource::ReturnTypeNotation + | PathSource::Delegation + | PathSource::ExternItemImpl => "function", PathSource::PreciseCapturingArg(..) => "type or const parameter", PathSource::Macro => "macro", PathSource::Module => "module", @@ -618,6 +624,9 @@ pub(crate) fn is_expected(self, res: Res) -> bool { _ => false, }, PathSource::Delegation => matches!(res, Res::Def(DefKind::Fn | DefKind::AssocFn, _)), + PathSource::ExternItemImpl => { + matches!(res, Res::Def(DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(..), _)) + } PathSource::PreciseCapturingArg(ValueNS) => { matches!(res, Res::Def(DefKind::ConstParam, _)) } @@ -640,8 +649,12 @@ fn error_code(self, has_unexpected_resolution: bool) -> ErrCode { (PathSource::Type | PathSource::DefineOpaques, false) => E0425, (PathSource::Struct(_), true) => E0574, (PathSource::Struct(_), false) => E0422, - (PathSource::Expr(..), true) | (PathSource::Delegation, true) => E0423, - (PathSource::Expr(..), false) | (PathSource::Delegation, false) => E0425, + (PathSource::Expr(..), true) + | (PathSource::Delegation, true) + | (PathSource::ExternItemImpl, true) => E0423, + (PathSource::Expr(..), false) + | (PathSource::Delegation, false) + | (PathSource::ExternItemImpl, false) => E0425, (PathSource::Pat | PathSource::TupleStruct(..), true) => E0532, (PathSource::Pat | PathSource::TupleStruct(..), false) => E0531, (PathSource::TraitItem(..) | PathSource::ReturnTypeNotation, true) => E0575, @@ -1091,7 +1104,7 @@ fn visit_fn(&mut self, fn_kind: FnKind<'ast>, _: &AttrVec, sp: Span, fn_id: Node *node_id, &None, &target.foreign_item, - PathSource::Expr(None), + PathSource::ExternItemImpl, ); } else { self.smart_resolve_path(*node_id, &None, &eii_macro_path, PathSource::Macro); @@ -2198,7 +2211,8 @@ fn resolve_elided_lifetimes_in_path( | PathSource::Struct(_) | PathSource::TupleStruct(..) | PathSource::DefineOpaques - | PathSource::Delegation => true, + | PathSource::Delegation + | PathSource::ExternItemImpl => true, }; if inferred { // Do not create a parameter for patterns and expressions: type checking can infer @@ -3004,7 +3018,7 @@ fn resolve_item(&mut self, item: &'ast Item) { item.id, &None, extern_item_path, - PathSource::Expr(None), + PathSource::ExternItemImpl, ); } } diff --git a/tests/ui/eii/eii-declaration-not-fn-issue-152337.rs b/tests/ui/eii/eii-declaration-not-fn-issue-152337.rs new file mode 100644 index 000000000000..8564a5a74847 --- /dev/null +++ b/tests/ui/eii/eii-declaration-not-fn-issue-152337.rs @@ -0,0 +1,12 @@ +// Regression test for ICE "unexpected sort of node in fn_sig()" (issue #152337). +// When the same name is used for a const and an #[eii] function, the declaration +// was incorrectly resolved to the const, causing fn_sig() to be called on a non-function. +#![feature(extern_item_impls)] + +const A: () = (); +#[eii] +fn A() {} //~ ERROR the name `A` is defined multiple times +//~^ ERROR expected function, found constant +//~| ERROR expected function, found constant + +fn main() {} diff --git a/tests/ui/eii/eii-declaration-not-fn-issue-152337.stderr b/tests/ui/eii/eii-declaration-not-fn-issue-152337.stderr new file mode 100644 index 000000000000..ea4ec604e7aa --- /dev/null +++ b/tests/ui/eii/eii-declaration-not-fn-issue-152337.stderr @@ -0,0 +1,27 @@ +error[E0428]: the name `A` is defined multiple times + --> $DIR/eii-declaration-not-fn-issue-152337.rs:8:1 + | +LL | const A: () = (); + | ----------------- previous definition of the value `A` here +LL | #[eii] +LL | fn A() {} + | ^^^^^^ `A` redefined here + | + = note: `A` must be defined only once in the value namespace of this module + +error[E0423]: expected function, found constant `self::A` + --> $DIR/eii-declaration-not-fn-issue-152337.rs:8:4 + | +LL | fn A() {} + | ^ not a function + +error[E0423]: expected function, found constant `A` + --> $DIR/eii-declaration-not-fn-issue-152337.rs:8:4 + | +LL | fn A() {} + | ^ not a function + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0423, E0428. +For more information about an error, try `rustc --explain E0423`.