-
Notifications
You must be signed in to change notification settings - Fork 13k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
type-check lang items #9307
Comments
I don't think this is milestone-worthy, because these are already implementation details. |
This leads to craziness like: #[no_std];
#[main]
#[lang="start"]
fn start() { }
or, more benignly: #[no_std];
#[lang="start"]
fn start() { }
#[main]
fn main() { } which just plain asserts:
or, more crazily: #[no_std];
#[lang="start"]
mod a { }
#[main]
fn main() { } which "just" ICEs:
Language items are the interface between the compiler and the language. They need to be well-defined and verified for correctness, IMO. |
(Nominating) |
This should not block 1.0. Assigning P-low. |
Still asserts with #![no_std]
#![feature(no_std,core,lang_items)]
extern crate core;
#[lang="start"]
fn main() {
}
#[lang = "stack_exhausted"] extern fn stack_exhausted() {}
#[lang = "eh_personality"] extern fn eh_personality() {}
#[lang = "panic_fmt"] fn panic_fmt() -> ! { loop{} } |
Triage: no changes |
I've looked at this a little and I think that the existing detection that #85339 added to traits could be expanded to include most or all of the lang items. This wouldn't be a full solution but it would help to stop some of the ICEs that occur on functions and structs that are lang items. |
Fix ICE when `start` lang item has wrong generics In my previous pr rust-lang#87875 I missed the requirements on the `start` lang item due to its relative difficulty to test and opting for more conservative estimates. This fixes that by updating the requirement to be exactly one generic type. The `start` lang item should have exactly one generic type for the return type of the `main` fn ptr passed to it. I believe having zero would previously *sometimes* compile (often with the use of `fn() -> ()` as the fn ptr but it was likely UB to call if the return type of `main` was not `()` as far as I know) however it also sometimes would not for various errors including ICEs and LLVM errors depending on exact situations. Having more than 1 generic has always failed with an ICE because only the one generic type is expected and provided. Fixes rust-lang#79559, fixes rust-lang#73584, fixes rust-lang#83117 (all duplicates) Relevant to rust-lang#9307 r? ``@cjgillot``
I want to push back on one part of the above message. I understand where @Mark-Simulacrum is coming from: Why do this work, when the thing we're checking is almost always part of libcore/libstd, and thus hopefully receiving significant review for correctness, especially when it comes to something like well-formedness. But: What about the developers who are making alternative libstds? That's a scenario where it seems like these checks would bring joy, not waste time. (Right?) In any case, even if it turns out that some of the introduced checks have non-trivial cost, I think we could still justify adding such checks if we can either 1. detect when we're compiling an "unblessed" libcore/libstd, or 2. put them under a |
FWIW, I think my perspective has changed a little since 2019, in part informed by the increased presence of alternative (or at least small change fork implementations of std + alloc (and in some cases core). So I think the checks are mostly valuable these days, particularly for any new lang items. I do think we should be cautious about making sure added checks are complete (i.e., actually verify correctness). While it is "just a bug" if we get it wrong, it is much easier in practice for folks to assume we're checking everything if we check partially, I think, especially in this area. |
Add basic checks for well-formedness of `fn`/`fn_mut` lang items This pull request fixes rust-lang#83471. Lang items are never actually checked for well-formedness (rust-lang#9307). This means that one can get an ICE quite easily, e.g. as follows: ```rust #![feature(lang_items)] #[lang = "fn"] trait MyFn { const call: i32 = 42; } fn main() { (|| 42)(); } ``` or this: ```rust #![feature(lang_items)] #[lang = "fn"] trait MyFn { fn call(i: i32, j: i32); } fn main() { (|| 42)(); } ``` Ideally, there should probably be a more comprehensive strategy for checking lang items for well-formedness, but for the time being, I have added some rudimentary well-formedness checks that prevent rust-lang#83471 and similar issues.
Fix ICE when `start` lang item has wrong generics In my previous pr rust-lang#87875 I missed the requirements on the `start` lang item due to its relative difficulty to test and opting for more conservative estimates. This fixes that by updating the requirement to be exactly one generic type. The `start` lang item should have exactly one generic type for the return type of the `main` fn ptr passed to it. I believe having zero would previously *sometimes* compile (often with the use of `fn() -> ()` as the fn ptr but it was likely UB to call if the return type of `main` was not `()` as far as I know) however it also sometimes would not for various errors including ICEs and LLVM errors depending on exact situations. Having more than 1 generic has always failed with an ICE because only the one generic type is expected and provided. Fixes rust-lang#79559, fixes rust-lang#73584, fixes rust-lang#83117 (all duplicates) Relevant to rust-lang#9307 r? `@cjgillot`
Fix ICE when `start` lang item has wrong generics In my previous pr rust-lang#87875 I missed the requirements on the `start` lang item due to its relative difficulty to test and opting for more conservative estimates. This fixes that by updating the requirement to be exactly one generic type. The `start` lang item should have exactly one generic type for the return type of the `main` fn ptr passed to it. I believe having zero would previously *sometimes* compile (often with the use of `fn() -> ()` as the fn ptr but it was likely UB to call if the return type of `main` was not `()` as far as I know) however it also sometimes would not for various errors including ICEs and LLVM errors depending on exact situations. Having more than 1 generic has always failed with an ICE because only the one generic type is expected and provided. Fixes rust-lang#79559, fixes rust-lang#73584, fixes rust-lang#83117 (all duplicates) Relevant to rust-lang#9307 r? ``@cjgillot``
Fix ICE when `start` lang item has wrong generics In my previous pr rust-lang#87875 I missed the requirements on the `start` lang item due to its relative difficulty to test and opting for more conservative estimates. This fixes that by updating the requirement to be exactly one generic type. The `start` lang item should have exactly one generic type for the return type of the `main` fn ptr passed to it. I believe having zero would previously *sometimes* compile (often with the use of `fn() -> ()` as the fn ptr but it was likely UB to call if the return type of `main` was not `()` as far as I know) however it also sometimes would not for various errors including ICEs and LLVM errors depending on exact situations. Having more than 1 generic has always failed with an ICE because only the one generic type is expected and provided. Fixes rust-lang#79559, fixes rust-lang#73584, fixes rust-lang#83117 (all duplicates) Relevant to rust-lang#9307 r? ```@cjgillot```
Fix ICE when `start` lang item has wrong generics In my previous pr rust-lang#87875 I missed the requirements on the `start` lang item due to its relative difficulty to test and opting for more conservative estimates. This fixes that by updating the requirement to be exactly one generic type. The `start` lang item should have exactly one generic type for the return type of the `main` fn ptr passed to it. I believe having zero would previously *sometimes* compile (often with the use of `fn() -> ()` as the fn ptr but it was likely UB to call if the return type of `main` was not `()` as far as I know) however it also sometimes would not for various errors including ICEs and LLVM errors depending on exact situations. Having more than 1 generic has always failed with an ICE because only the one generic type is expected and provided. Fixes rust-lang#79559, fixes rust-lang#73584, fixes rust-lang#83117 (all duplicates) Relevant to rust-lang#9307 r? ````@cjgillot````
Fix ICE when `start` lang item has wrong generics In my previous pr rust-lang#87875 I missed the requirements on the `start` lang item due to its relative difficulty to test and opting for more conservative estimates. This fixes that by updating the requirement to be exactly one generic type. The `start` lang item should have exactly one generic type for the return type of the `main` fn ptr passed to it. I believe having zero would previously *sometimes* compile (often with the use of `fn() -> ()` as the fn ptr but it was likely UB to call if the return type of `main` was not `()` as far as I know) however it also sometimes would not for various errors including ICEs and LLVM errors depending on exact situations. Having more than 1 generic has always failed with an ICE because only the one generic type is expected and provided. Fixes rust-lang#79559, fixes rust-lang#73584, fixes rust-lang#83117 (all duplicates) Relevant to rust-lang#9307 r? ````@cjgillot````
These aren't currently well-defined by the language. If you define anything with a somewhat matching LLVM signature, it will compile. Not only does it not care about the type signatures matching what it expects, there is no handling for these being defined on the wrong types of AST nodes.
The text was updated successfully, but these errors were encountered: