Skip to content

Commit

Permalink
Rollup merge of rust-lang#92510 - inquisitivecrystal:foreign-block, r…
Browse files Browse the repository at this point in the history
…=cjgillot

Don't resolve blocks in foreign functions

Although it is an error for a foreign function to have a block, it is still possible at the level of the AST. rust-lang#74204 made AST lowering skip over blocks belonging to foreign functions, since they're invalid. However, resolve still treated these blocks normally, resulting in a mismatch between the HIR and resolve, which could cause an ICE under certain circumstances. This PR changes resolve to skip over blocks belonging to foreign functions, as AST lowering does.

Fixes rust-lang#91370.

r? `@cjgillot`
  • Loading branch information
matthiaskrgr committed Jan 6, 2022
2 parents 1786cba + 42de973 commit 21fe214
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 3 deletions.
13 changes: 10 additions & 3 deletions compiler/rustc_resolve/src/late.rs
Original file line number Diff line number Diff line change
Expand Up @@ -520,9 +520,16 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
}
fn visit_fn(&mut self, fn_kind: FnKind<'ast>, sp: Span, _: NodeId) {
let rib_kind = match fn_kind {
// Bail if there's no body.
FnKind::Fn(.., None) => return visit::walk_fn(self, fn_kind, sp),
FnKind::Fn(FnCtxt::Free | FnCtxt::Foreign, ..) => FnItemRibKind,
// Bail if the function is foreign, and thus cannot validly have
// a body, or if there's no body for some other reason.
FnKind::Fn(FnCtxt::Foreign, _, sig, ..) | FnKind::Fn(_, _, sig, .., None) => {
// We don't need to deal with patterns in parameters, because
// they are not possible for foreign or bodiless functions.
self.visit_fn_header(&sig.header);
visit::walk_fn_decl(self, &sig.decl);
return;
}
FnKind::Fn(FnCtxt::Free, ..) => FnItemRibKind,
FnKind::Fn(FnCtxt::Assoc(_), ..) => NormalRibKind,
FnKind::Closure(..) => ClosureOrAsyncRibKind,
};
Expand Down
12 changes: 12 additions & 0 deletions src/test/ui/foreign/issue-91370-foreign-fn-block-impl.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Regression test for issue #91370.

extern {
//~^ `extern` blocks define existing foreign functions
fn f() {
//~^ incorrect function inside `extern` block
//~| cannot have a body
impl Copy for u8 {}
}
}

fn main() {}
21 changes: 21 additions & 0 deletions src/test/ui/foreign/issue-91370-foreign-fn-block-impl.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
error: incorrect function inside `extern` block
--> $DIR/issue-91370-foreign-fn-block-impl.rs:5:8
|
LL | extern {
| ------ `extern` blocks define existing foreign functions and functions inside of them cannot have a body
LL |
LL | fn f() {
| ________^___-
| | |
| | cannot have a body
LL | |
LL | |
LL | | impl Copy for u8 {}
LL | | }
| |_____- help: remove the invalid body: `;`
|
= help: you might have meant to write a function accessible through FFI, which can be done by writing `extern fn` outside of the `extern` block
= note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html

error: aborting due to previous error

0 comments on commit 21fe214

Please sign in to comment.