Skip to content
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

fix array element type algorithm to avoid selecting never #6511

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

xunilrj
Copy link
Contributor

@xunilrj xunilrj commented Sep 7, 2024

Description

This PR fixes the array element type selection algorithm to avoid selecting Never.

Checklist

  • I have linked to any relevant issues.
  • I have commented my code, particularly in hard-to-understand areas.
  • I have updated the documentation where relevant (API docs, the reference, and the Sway book).
  • I have added tests that prove my fix is effective or that my feature works.
  • I have added (or requested a maintainer to add) the necessary Breaking* or New Feature labels where relevant.
  • I have done my best to ensure that my PR adheres to the Fuel Labs Code Review Standards.
  • I have requested a review from the relevant team or maintainers.

@xunilrj xunilrj requested a review from a team as a code owner September 7, 2024 08:38
Copy link

codspeed-hq bot commented Sep 7, 2024

CodSpeed Performance Report

Merging #6511 will improve performances by 20.79%

Comparing xunilrj/fix-array-elem-type-alg (7d2e15f) with master (ba153b2)

Summary

⚡ 1 improvements
✅ 21 untouched benchmarks

Benchmarks breakdown

Benchmark master xunilrj/fix-array-elem-type-alg Change
document_symbol 5.2 ms 4.3 ms +20.79%

Comment on lines +1873 to +1875
// if the element type is still unknown, and all elements are Never,
// fallback to unit
let initial_type = if matches!(initial_type, TypeInfo::Unknown) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a problem with using Unknown instead of unit as the result in this case?

If the type is still Unknown after unification, then we should throw an error because the type could not be determined. Otherwise it seems to me that using Unknown here solves the entire issue.

Copy link
Contributor Author

@xunilrj xunilrj Sep 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unit is how Rust does it.

fn main() {
    let mut a = None;
    loop {
        a = Some([break]);
    }
    println!("{}", std::any::type_name_of_val(&a));
}

will print core::option::Option<[(); 1]>

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But giving an error in this case does not seem wrong to me. We just need to decide which we prefer.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it matters much so long as we guarantee that the unannotated type of [] is [();0].

I suppose in the broadest sense, the programmer's intent with a program like this is unambiguous and so it's not really erroneous. It's just weird, but it's fully deterministic and since the elements aren't used at all, any zero sized type will do.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so long as we guarantee that the unannotated type of [] is [();0]

But this is not what Rust does. [] is whatever the context says. If there is no context, then it fails.
This "decay" to Unit only happens for "arrays without typing context and all elements are never".

Changing the program above to an empty array and it fails.

image

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that in this case ("arrays without typing context and all elements are never") we have four options:
1 - infer the array element as never; so something like [!;1];
2 - infer the whole array as never;
3 - decay into a zero-sized type, in this case, unit;
4 - give an error.

1 and 2 create this complicated case of how to deal with "generic types with never".
I think 4 is totally reasonable in this case.
But I implemented 3 just because it is what Rust does.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having thought about it some more I'm ok with either solution TBH.

We're trying to solve a degenerate case where an array of Never elements is used in a way that is inconsistent with the Never type. The array will never be constructed (because that's what Never means), so the inconsistency will also never be executed. Whether the compiler calls that a type error or piece of allowable dead code is really not worth making a big deal out of. It's a type violation in dead code.

@xunilrj xunilrj requested a review from jjcnn September 10, 2024 14:57
@xunilrj xunilrj force-pushed the xunilrj/fix-array-elem-type-alg branch from 72a6512 to 7d2e15f Compare September 16, 2024 10:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants