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

Accept Enum::<Param>::Variant {} over Enum::Variant::<Param> {} #69363

Closed
wants to merge 4 commits into from

Conversation

estebank
Copy link
Contributor

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Feb 21, 2020
@rust-highfive

This comment has been minimized.

@petrochenkov
Copy link
Contributor

So, I remember the rule here - paths in "value" contexts get all their omitted generic arguments filled with inference variables (_), but paths in "type" contexts get all their omitted generic arguments filled with defaults or errors if some necessary defaults don't exist.

All the examples in #69356 and in the tests are in "value" context.

I did touch the implementation of this at some point, but it was rewritten so many times since then that I have no idea how this works now.

src/librustc_ast_lowering/path.rs Show resolved Hide resolved
src/librustc_typeck/astconv.rs Outdated Show resolved Hide resolved
@petrochenkov petrochenkov added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Feb 23, 2020
@petrochenkov
Copy link
Contributor

petrochenkov commented Feb 23, 2020

IIRC, @varkor the author of the current implementation?
cc him then.

@estebank estebank changed the title [Do not merge yet] Treat ExprKind::Path and ExprKind::Struct the same for the purposes of path checking Accept Enum::<Param>::Variant {} over Enum::Variant::<Param> {} Feb 24, 2020
@rust-highfive

This comment has been minimized.

@estebank
Copy link
Contributor Author

estebank commented Feb 25, 2020

I've got a commit to make the lint allow by default if that is preferable.

Edit: Given #69363 (comment) I guess we need to make it allow by default.

@rust-highfive

This comment has been minimized.

@estebank estebank added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Feb 25, 2020
Comment on lines +59 to 75
Res::Def(DefKind::Variant, def_id)
if i + 2 == proj_start && segment.args.is_some() =>
{
// Handle `Enum::<Param>::Variant {}`.
// We need to choose one here so that the method `res_to_ty` in
// `astconv` works correctly, but it has to be *only* one, so track
// whether we've already set the `DefId` in the previous segment.
type_param_in_enum = true;
Some(parent_def_id(self, def_id))
}
Res::Def(DefKind::Variant, def_id)
if i + 1 == proj_start
&& (segment.args.is_some() || !type_param_in_enum) =>
{
// Handle `Enum::Variant::<Param> {}`.
Some(parent_def_id(self, def_id))
}
Copy link
Member

@eddyb eddyb Feb 25, 2020

Choose a reason for hiding this comment

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

Two things here:

  1. you can avoid mutable state by looking at p.segments
    • btw I doubt a bit that .args.is_some() is the correct way to check this, it might be true even for ::<> which I'm not sure if it's compatible with the similar check in typeck
  2. these only make sense if the param mode is explicit, which it can never be for Expr::Struct right now (<Enum>::Variant {...} is not valid syntax, and Enum::Variant is not valid in type paths yet, only one of these two could actually be relevant here)
    • the comments referring to Enum::Variant {...} are therefore inaccurate IMO
    • this needs some extra checks, probably for the param mode being explicit
    • it's really mostly forward compat for enum variant types so you could just as well add an assert that DefKind::Variant parts are never ParamMode::Explicit

@@ -531,6 +538,7 @@ declare_lint_pass! {
PATTERNS_IN_FNS_WITHOUT_BODY,
MISSING_FRAGMENT_SPECIFIER,
LATE_BOUND_LIFETIME_ARGUMENTS,
TYPE_PARAM_ON_VARIANT_CTOR,
Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure I would include CTOR in the name. Also, this isn't limited to type parameters.

I'd call it VARIANT_GENERICS or VARIANT_GENERIC_ARGS.

Comment on lines +2324 to +2344
pub fn prohibit_multiple_params<'a, T: IntoIterator<Item = &'a hir::PathSegment<'a>>>(
&self,
segments: T,
) -> bool {
let segments_with_params = segments
.into_iter()
.filter_map(|segment| segment.args.map(|arg| arg.span))
.collect::<Vec<_>>();
if segments_with_params.len() <= 1 {
return false;
}
self.tcx()
.sess
.struct_span_err(
segments_with_params,
"multiple segments with type parameters are not allowed",
)
.note("only a single path segment can specify type parameters")
.emit();
true
}
Copy link
Member

Choose a reason for hiding this comment

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

I think this is unnecessarily complicated, it doesn't distinguish this "enum vs variant" situation from others (e.g. trying to pass generic args to a mod) and it's wrong with generic associated items like methods or GATs.

This could be a help message on the error from prohibit_generics, such as pointing to the enum segment and saying "this segment already specified generic args for the enum" or something.

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 this is unnecessarily complicated, it doesn't distinguish this "enum vs variant" situation from others (e.g. trying to pass generic args to a mod) and it's wrong with generic associated items like methods or GATs.

That check is being done when called. If it were called without that check it would indeed be incorrect.

This could be a help message on the error from prohibit_generics, such as pointing to the enum segment and saying "this segment already specified generic args for the enum" or something.

Wanted to separate this from E0109 to potentially give it its own error code to explain that this will never be supported as opposed to the more generic current error.

Copy link
Member

Choose a reason for hiding this comment

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

to explain that this will never be supported

What do you mean? Generics on both the enum and a variant is a plausible feature (GADT), and generics on modules have been talked about in the past.

The error message looks pretty misleading to me, it seems to claim some absolute truth.

Comment on lines +2542 to +2546
if sp.hi() == sp.lo() || sp == DUMMY_SP || sp.parent().is_some() {
// The params were not written by the user, but rather derived. These are expected.
// `Enum::Variant` where `Variant` has inferred lifetimes.
return;
}
Copy link
Member

Choose a reason for hiding this comment

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

I don't like this check, and you can get rid of the lifetimes for now (they shouldn't be added to value paths anyway).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agree. It's hacky as hell.

you can get rid of the lifetimes for now

How?

they shouldn't be added to value paths anyway

I've spent too much time trying to figure out of a way of making this change without affecting currently accepted code.

Copy link
Member

Choose a reason for hiding this comment

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

Basically you want all Expr::Struct with variant paths to behave in HRI lowering like they did when you had removed the DefKind::Variant arm.
You don't want the elision lifetimes being injected at all.

They're for fn foo(x: &T) -> Enum::Variant, or perhaps <Enum>::Variant {...} (neither of which compile right now), not Enum::Variant {...}.

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 if none of the PathSegments have the elision lifetimes injected (in src/librustc_ast_lowering/path.rs) then you get knock down errors about the type for a HirId not existing .

Copy link
Member

Choose a reason for hiding this comment

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

then you get knock down errors about the type for a HirId not existing

I don't recall you bringing this up, I thought it just worked while you had that arm removed? I don't see why it would, other value paths have no lifetimes injected into them at all.

@bors
Copy link
Contributor

bors commented Feb 27, 2020

☔ The latest upstream changes (presumably #68434) made this pull request unmergeable. Please resolve the merge conflicts.

@petrochenkov
Copy link
Contributor

r? @varkor

@JohnCSimon JohnCSimon added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Mar 11, 2020
@Dylan-DPC-zz
Copy link

@estebank waiting on your answers to the latest questions on the above review. Thanks

@joelpalmer joelpalmer added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Mar 30, 2020
@joelpalmer joelpalmer added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Apr 9, 2020
@Dylan-DPC-zz
Copy link

Closing this due to inactivity

@Dylan-DPC-zz Dylan-DPC-zz added S-inactive Status: Inactive and waiting on the author. This is often applied to closed PRs. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Apr 9, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-inactive Status: Inactive and waiting on the author. This is often applied to closed PRs.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Possibly incorrect syntax Enum::<Type, Params>::Variant allowed since 1.33
10 participants