Does the "avoid prefixing the type with the name of the module" style rule still apply?

I find synonyms(in general) make code both harder to read and to write. When reading, you need to be aware both about the definition and the alias. When writing, you need to actively choose one.

This seems like an uninteresting question, and I generally try to rule-of-thumb all uninteresting and unimportant questions, so that I can think about interesting ones.

Somewhat similarly, for intra-crate imports, I always use use crate::foo::bar, and not use super::bar, not because the former is better (the question is irrelevant) but because it gives me less space to deliberate.

9 Likes

I think that the problem should be solved with the tooling, not by changing code styles.

E.g.: we may create an annotation that suggests that the given item should be used with module prefix.

mod smt {
    #[use_should_prefix("smt")] // I'm bad at naming, but you've got the idea
    struct Error { /* ... */ }
}

Then clippy could warn about unprefixed uses of the item (Error instead of smt::Error in this example) and IDEs could suggest right paths.

4 Likes

In the immortal words of Mr. McRane as "Emil" in Robocop, "I like it"!

Would that warn when imported as use smt::Error as SmtError? Or any other prefix the user likes really.

I think it's enough to document this stuff somewhere. "The general convention when using common names or free-style functions is to not import them directly but use them through the parent module". Then it's up to the user to decide what fits best.

I'm not understanding that code sample. Is it equivalent to the following?

use image::png::Decoder as PngDecoder;
let _ = PngDecoder::new(...);

In that case the gains don't seem that big, and use image::png already enables the very similar png::Decoder (a bit more noise on use, but shorter to import!).

1 Like

I think it should. Actually I think it should warn about any direct (not glob ::*) import of Error, doesn't count with or without renaming + any mention of Error if imported by glob import.

The point is - if you want to follow this convention, you probably want to notice when you've mistaken (and that can happen frequently because IDEs are always suggesting using item w/o prefix)

That seems fixable, at least for the common case of Error and Result types, the IDE could detect those names and suggest useing the module and a semi-qualified path.

1 Like

Sure. Though this won't help in cases like Decoders from image. That's the reason I propose an annotation.

I would not like this:

  1. Let us trust the programmer to decide this for him or herself. Rust is already quite a "nanny" language with default warnings about names not following suggested upper/lowercase patterns. I don't think it needs to also care about how the programmer uses the tool that is use statements.

  2. Not everyone is using an IDE and I don't think "let the IDE handle it" should be a valid argument. Let people use IDEs as an enhancement, but don't build the language around the assumption that they're always available (I edit code I'm different contexts, such as via GitHub quick edits and with my editor).

The lint can be allow-by-default. I also don't think this approach is "let the IDE handle it", it's more like "let the IDE also handle it"

Yeah, I get that it would be allowed by default β€” but simply seeing the warning will make me feel that I'm doing something wrong and I'll then have to investigate how to a) fix the worning, or b) silence the warning.

A lint can have one of 3 possible states:

  1. DENY - means it is a compiler error if the lint's requirements are not met, so, until you correct the issue, your program will not compile fully and link.
  2. WARN - means that you'll receive a warning, but your program will still compile and link
  3. ALLOW - means that you won't receive a warning or any error at all (the lints requirements will be ignored).

So, if it is "Allow by Default", that means you'll never see a warning unless you explicitly set it to WARN or DENY in your program.

3 Likes

Also a fourth state, FORBID: the same as DENY, but cannot be set to a lower level internally.

(E.g. with #![deny(unsafe)], I can #[allow(unsafe)] locally. With #![forbid(unsafe)], #[allow(unsafe)] is a compile error.)

2 Likes

Thanks, I misunderstood this! That seems much better indeed since people who like the feature can use it without consequence for the rest

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.