6

RFC: Attributes in function return type position by not-my-profile · Pull Reques...

 3 years ago
source link: https://github.com/rust-lang/rfcs/pull/3201
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Conversation

Copy link

not-my-profile commented 17 days ago

edited

#2565 introduced attributes for function parameters. This RFC proposes the logical next step: allowing attributes for function return types. This RFC is less radical than #2602 which proposes that attributes should be allowed allowed to be attached nearly everywhere (lifetimes, types, bounds, and constraints), which has been argued to go a bit too far resulting in too much cognitive load. This RFC hopes to increase the expressiveness of DSLs without posing too much cognitive load.

Rendered

Copy link

Contributor

Diggsey commented 17 days ago

edited

Is there any precedent in other languages for allowing attributes on return types? It looks out of place to me, but it might just be because I'm not used to seeing attributes in that position.

Presumably if you wish to place a return type attribute on a unit-returning function, you must explicitly state the return type? ie.

I see this is covered now.

fn example() -> #[attr] () {
}

Also, #2565 allows attributes on closure arguments as well as functions. This RFC should also state whether closure return types can be annotated.

Copy link

Member

scottmcm commented 17 days ago

So attributes on parameters were clearly helpful since there are multiple -- a function-level attribute would have had to match up the name or something, which would be awkward.

But the distinction between a function and its return type are much less clear-cut to me. For example, I'm not sure it's clearer to say that the the Vec<Page> is returned as json than to just say that the example HTTP endpoint returns json. Similarly, I'm not sure it'd be better to have

fn to_lowercase(&self) -> #[must_use] String;

than the current

#[must_use]
fn to_lowercase(&self) -> String;

even if you could argue that it's the return value that needs to be used. (And I acknowledge that the RFC doesn't propose changing must_use, but it seemed a useful study.)

So I think overall my first instinct here is "weak no due to insufficient motivation". But that's weakly held, so could change.

Copy link

Contributor

clarfonthey commented 17 days ago

Small nit: could you define DSL in the RFC text please? Since I'm not quite sure what you mean there.

Copy link

Author

not-my-profile commented 16 days ago

edited

@Diggsey Yes as I wrote in the RFC unit-returns would need to be made explicit. I am not aware of a precedent for return type attributes in other languages, which is also why I put that very question under "unresolved questions". Thanks, good catch with the closures! I think for consistency attributes should be supported for their return types as well (I updated the RFC accordingly).

@clarfonthey Thanks, I clarified that DSL stands for domain-specific language.

@scottmcm Thanks, you raise a good points. I agree that the motivation for return type attributes is weaker than for parameter attributes but I think for certain DSLs they would still be desirable enough to justify their addition to the language. I agree that the json return type wasn't the best example ... I updated the motivation with a better example:

#[wasm_bindgen]
impl RustLayoutEngine {
    pub fn layout(
        &self,
        #[type = "MapNode[]"] nodes: Vec<JsValue>,
        #[type = "MapEdge[]"] edges: Vec<JsValue>
    ) -> #[type = "MapNode[]"] Vec<JsValue> {
        ..
    }
}

is in my opinion clearly preferable to

#[wasm_bindgen]
impl RustLayoutEngine {
    #[return_type = "MapNode[]"]
    pub fn layout(
        &self,
        #[type = "MapNode[]"] nodes: Vec<JsValue>,
        #[type = "MapEdge[]"] edges: Vec<JsValue>
    ) -> Vec<JsValue> {
        ..
    }
}

So I think return type attributes would primarily be useful for specifying another return type that the function return type is somehow mapped to via the generated code. In that case having both the actual and the "mapped" return types next to each other makes the code more readable and facilitates maintenance (if one is updated the other type likely should be updated as well, which is easier to do when they're next to each other).

Copy link

Boboseb commented 16 days ago

Is there any precedent in other languages for allowing attributes on return types? It looks out of place to me, but it might just be because I'm not used to seeing attributes in that position.

C# allows attribute on return values https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/attributes/#attribute-targets but I don't remember any example

If you're looking for other example of confusing language that can put attributes everywhere, we can take C++

[[function]]
auto [[type1]] 
my_function([[arg]] int [[type2]] * [[type3]] my_arg) [[function_type]] 
        ->  int [[type4]] * [[type5]] {
    return my_arg;
}

Notice that it is hard to see what exactly is annotated. Unlike in rust, the attribute sometimes comes before, sometimes after what it describes. I'm not even quite sure about what i annotated, but i think type1 and type5 annotates the return type (int*), and function_type annotates the function type (in this case int* (*) (int *)), while [[function]] annotates the whole function.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

No reviews

Assignees

No one assigned

Labels
Projects

None yet

Milestone

No milestone

Linked issues

Successfully merging this pull request may close these issues.

None yet

7 participants

Recommend

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK