rustfmt icon indicating copy to clipboard operation
rustfmt copied to clipboard

Don't remove const generic when using `#[feature(generic_const_items)]`

Open ytmimi opened this issue 1 year ago • 11 comments

Fixes #5995

Added support for rewriting generics on const items.

ytmimi avatar Dec 29 '23 00:12 ytmimi

Could you add a test for where-clauses, too? That would be great! Thanks in advance :)

fmease avatar Feb 08 '24 22:02 fmease

@fmease happy to add the test case, but would you mind providing the code snippet. I'm not as familiar with this feature as you are.

ytmimi avatar Feb 08 '24 22:02 ytmimi

Sure, for example:

pub const K<T>: Option<T> = None
where
    String: From<T>;

And:

pub trait Trait<T: ?Sized> {
    const C<'a>: &'a T
    where
        T: 'a + Eq;
}

fmease avatar Feb 08 '24 23:02 fmease

Note that generic const items don't have an entry inside the Style Guide yet as you might or might not have noticed. However, the formatting should basically follow the new^1 formatting of type aliases and associated types (except that they don't need to deal with legacy-style leading where clauses, cc #5887).

fmease avatar Feb 08 '24 23:02 fmease

Looks like there's still a little work to be done. Formatting with this branch on the snippets you provided removes the where clauses:

input:

pub const K<T>: Option<T> = None
where
    String: From<T>;

pub trait Trait<T: ?Sized> {
    const C<'a>: &'a T
    where
        T: 'a + Eq;
}

output:

pub const K<T>: Option<T> = None;

pub trait Trait<T: ?Sized> {
    const C<'a>: &'a T;
}

ytmimi avatar Feb 09 '24 00:02 ytmimi

Yeah, seems to need rewrite_where_clause somewhere.

fmease avatar Feb 09 '24 04:02 fmease

Just double checking, but where clauses are new to const items now that they can be generic with the #[feature(generic_const_items)] , right?

ytmimi avatar Feb 09 '24 16:02 ytmimi

Yes, they are part of generic_const_items and don't exist outside of the feature.

fmease avatar Feb 09 '24 17:02 fmease

Note to self, unlike the deprecated type alias syntax, it's not possible to place the where clause before the assignment. I put together this small snippet that compiles:

#![feature(generic_const_items)]

pub const K<T>: Option<T> = None
where
    String: From<T>,
    T: std::fmt::Debug;


#[derive(Debug)]
struct ToString;

impl From<ToString> for String {
    fn from(_value: ToString) -> Self {
        String::new()
    }
}

fn main() {
    println!("{:?}", K::<ToString>);
}

But when I switch the order of the where clause and the assignment I get the following compilation errors:

#![feature(generic_const_items)]

pub const K<T>: Option<T>
where
    String: From<T>,
    T: std::fmt::Debug,
 = None;

#[derive(Debug)]
struct ToString;

impl From<ToString> for String {
    fn from(_value: ToString) -> Self {
        String::new()
    }
}

fn main() {
    println!("{:?}", K::<ToString>);
}
error: where clauses are not allowed before const item bodies
 --> example.rs:5:1
  |
4 |   pub const K<T>: Option<T>
  |             - while parsing this const item
5 | / where
6 | |     String: From<T>,
7 | |     T: std::fmt::Debug,
  | |_______________________^ unexpected where clause
8 |   = None;
  |     ---- the item body
  |
help: move the body before the where clause
  |
5 ~ = None where
6 |     String: From<T>,
7 ~     T: std::fmt::Debug,;
  |

error: aborting due to 1 previous error

ytmimi avatar Feb 17 '24 19:02 ytmimi