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

Remove impl Foo for .. {} in favor auto trait Foo {} #46480

Closed
wants to merge 8 commits into from

Conversation

leoyvens
Copy link
Contributor

@leoyvens leoyvens commented Dec 3, 2017

The new syntax was introduced and the old one deprecated in #45247. This removes the old syntax and simplifies some code as a result. Some errors that were possible with the old syntax no longer make sense. WF checking is moved to an ast validation.

There is some conflict with #46455, nothing serious. I guess this PR should be preferred where there is a conflict.

@kennytm kennytm added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Dec 4, 2017
@leoyvens
Copy link
Contributor Author

leoyvens commented Dec 4, 2017

Got error on rustdoc's error index test, it's not parsing auto trait. It seems the bootstrap rustdoc was not updated yet?

@kennytm
Copy link
Member

kennytm commented Dec 4, 2017

@leodasvacas Try to add a # fn main() {} at the end of the E0198 test. It seems rustdoc wraps a fn main() { … } around the code body. It also shows auto trait cannot be declared inside a function 🤔

https://play.rust-lang.org/?gist=5e9637830e8e6cb05b3f48a8e7bc5cf7&version=nightly

@leoyvens
Copy link
Contributor Author

leoyvens commented Dec 4, 2017

@kennytm Nailed it as usual, fixed it.

// Our goal here is to parse an arbitrary path `a::b::c` but not something that starts
// like a path (1 token), but it fact not a path.
// `union::b::c` - path, `union U { ... }` - not a path.
// `crate::b::c` - path, `crate struct S;` - not a path.
} else if self.token.is_path_start() &&
!self.token.is_qpath_start() &&
!self.is_union_item() &&
!self.is_crate_vis() {
!self.is_crate_vis() &&
Copy link
Member

Choose a reason for hiding this comment

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

Ditto

(self.token.is_keyword(keywords::Auto)
&& self.look_ahead(1, |t| t.is_keyword(keywords::Trait)))
|| // unsafe auto trait
(self.token.is_keyword(keywords::Unsafe) &&
Copy link
Member

Choose a reason for hiding this comment

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

Trailing whitespace

[00:03:11] tidy error: /checkout/src/libsyntax/parse/parser.rs:3946: trailing whitespace
[00:03:11] tidy error: /checkout/src/libsyntax/parse/parser.rs:4060: trailing whitespace

self.err_handler().span_err(item.span,
"auto traits cannot have generics");
struct_span_err!(self.session, item.span, E0567,
"Auto traits cannot have type parameters").emit();
Copy link
Contributor

@petrochenkov petrochenkov Dec 4, 2017

Choose a reason for hiding this comment

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

"Auto" -> "auto", error messages are not normally capitalized.
Also "type parameters" -> "generic parameters" and the condition a few lines above is incorrect, it should use !generics.is_parameterized(), because lifetime parameters are disallowed as well (they are currently rejected on impls for ..).

self.err_handler().span_err(item.span,
"auto traits cannot have super traits");
struct_span_err!(self.session, item.span, E0568,
"Auto traits cannot have predicates").emit();
Copy link
Contributor

Choose a reason for hiding this comment

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

The message was better before, IMO.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Should I use the new error code and the old error message?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, why not.

E0533, // `{}` does not name a unit variant, unit struct or a constant
// E0563, // cannot determine a type for this `impl Trait`: {} // removed in 6383de15
E0564, // only named lifetimes are allowed in `impl Trait`,
// but `{}` was found in the type `{}`
E0567, // auto traits can not have type parameters
E0568, // auto-traits can not have predicates,
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you comment out the obsoleted error codes instead of removing them?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Tidy is merciless, it gives me duplicate error codes even if it's commented out.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah, right, they are not removed, just moved to AST validation.

@@ -6167,7 +6150,8 @@ impl<'a> Parser<'a> {
let is_auto = if self.eat_keyword(keywords::Trait) {
IsAuto::No
} else {
self.eat_auto_trait();
self.eat_keyword(keywords::Auto);
Copy link
Contributor

Choose a reason for hiding this comment

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

Rule of thumb: eat_keyword shouldn't be used unless you use the returned result.
expect_keyword or simply bump would be better here.

@petrochenkov
Copy link
Contributor

LGTM, modulo comments.
I think this should be landed before #46455.

The only question is - is it too soon to remove this or not?
Should we wait a few more weeks until the new auto trait syntax hits a stable release?
I'm nominating this so lang team could briefly discuss this and confirm "yep, let's remove this" (or not).
Also pinging a couple of people from the Servo/nightly ecosystem @dtolnay @SimonSapin

@petrochenkov petrochenkov added I-nominated T-lang Relevant to the language team, which will review and decide on the PR/issue. S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. S-waiting-on-team Status: Awaiting decision from the relevant subteam (see the T-<team> label). and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Dec 4, 2017
@SimonSapin
Copy link
Contributor

I general we only deprecate or remove stuff once the replacement has reached the stable channel. If a project (even using unstable features) builds without warnings on all three release channels, it should be possible to keep it that way.

@kennytm kennytm removed the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Dec 5, 2017
@bors
Copy link
Contributor

bors commented Dec 7, 2017

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

@bors
Copy link
Contributor

bors commented Dec 14, 2017

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

@bors
Copy link
Contributor

bors commented Dec 19, 2017

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

@nikomatsakis
Copy link
Contributor

@SimonSapin

I general we only deprecate or remove stuff once the replacement has reached the stable channel. If a project (even using unstable features) builds without warnings on all three release channels, it should be possible to keep it that way.

Can you say a bit more about this? Are you imagining that e.g. the unstable syntax is removed with #[cfg]?

@SimonSapin
Copy link
Contributor

Uh, what I wrote doesn’t make sense. A project that uses unstable features cannot build on beta or stable. I was thinking of deprecating stable features. Never mind me :)

@bors
Copy link
Contributor

bors commented Dec 21, 2017

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

@hanna-kruppe
Copy link
Contributor

hanna-kruppe commented Jan 6, 2018

You can blame crossbeam if you want (I wouldn't, this particular breakage is only obvious in hindsight -- perfectly competent programmers could have missed it, and indeed did). That doesn't change the fact that countless transitive dependencies of crossbeam would stop compiling on stable for no good reason -- there's no soundness bug and no gross negligence on crossbeam's part, and preventing the breakage isn't even difficult AFAICT. Breaking all this code and forcing it to update would be user-hostile IMO.

@bluss
Copy link
Member

bluss commented Jan 6, 2018

@rkruppe What about splitting the deprecation so that it functionally stops working, but it still parses (and emits some kind of warning?)

@kennytm kennytm added I-needs-decision Issue: In need of a decision. S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-blocked Status: Marked as blocked ❌ on something else such as an RFC or other implementation work. labels Jan 6, 2018
@hanna-kruppe
Copy link
Contributor

@bluss That's pretty much what I suggested earlier, just without the warning. I don't see a big need for a warning -- it can just error if the old syntax remains after cfg stripping, and be silently stripped otherwise. But that's a minor difference. The important part is that the old syntax still parses but emits an error soon after cfg stripping.

@petrochenkov
Copy link
Contributor

Ha, this is an interesting issue.
It looks like we can't remove any old syntax from the parser if stable crates can use

#[cfg(nightly)]
old_syntax

In this case we need to keep minimal support for any old syntax in the parser and AST (e.g. ItemKind::Obsolete(ObsoleteKind)) and report errors a bit later, at least after configuration (in AST validation, for example).


However, the larger effect seems pretty scary - we can't experiment with any new features in rustc if they require parser support because we'll may have to keep this support forever.

@dtolnay
Copy link
Member

dtolnay commented Jan 6, 2018

However, the larger effect seems pretty scary - we can't experiment with any new features in rustc if they require parser support because we'll may have to keep this support forever.

Lazily parsing item bodies would mitigate this to some extent right?

#[cfg(unstable)]
mod future {
    ~wacky FUTURE _syntax!

    impl RemovedSyntax for .. {}
}

If the braced module body is parsed after cfg stripping, this should be okay. We already support this because it is what happens for out-of-line modules #[cfg(unstable)] mod future;.

@hanna-kruppe
Copy link
Contributor

However, the larger effect seems pretty scary - we can't experiment with any new features in rustc if they require parser support because we'll may have to keep this support forever.

Yeah, quite unfortunate. There is one mitigating factor, though: Any such features introduced now or in the future will have the same problem (parser error even if cfg'd out) on all previous releases. Therefore, it's reasonably possible that a crate author that makes the same mistake the crossbeam authors made will get bug reports from users on old stable releases, alerting them of the problem. impl Trait for .. {} was grandfathered in from before 1.0 so it didn't benefit from this.

We could declare such changes "acceptable breakage" and start recommending crates use macros for conditional use of nightly-only syntax features. If enough crates follow this guideline (aided by the mitigating factor described above), or the feature was never in widespread use anyway, we could sometimes get away with just removing parser support. But crossbeam is big enough that we really shouldn't break it even if that had been long-standing policy. It's still possible that any given feature winds up in a popular crate that cfg-gated it improperly, but it hopefully limits the amount of obsolete syntax the parser needs to accumulate support for.

@petrochenkov
Copy link
Contributor

@dtolnay
Hiding the unstable syntax in an out-of-line module or in a macro would work right now, without adding lazy parsing of in-line modules, but it didn't help crossbeam that used impl for .. without any lazily parseable "container".
So it's probably something that needs to be "fixed" by teaching in the first place (and using CI with older rustc versions), as @rkruppe described in #46480 (comment).

@leoyvens
Copy link
Contributor Author

leoyvens commented Jan 6, 2018

I agree the current impact of breakage here is not acceptable. I'll update this patch to have the minimum necessary support for the deprecated syntax. @petrochenkov is it viable to support this only in the parser but not in the AST?

@petrochenkov
Copy link
Contributor

@leodasvacas

is it viable to support this only in the parser but not in the AST?

The impl for .. item should leave at least some trace, otherwise you won't be able to report an error after cfg expansion.
Keeping it in AST should be the simplest solution.

@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 Jan 6, 2018
@bors
Copy link
Contributor

bors commented Jan 7, 2018

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

@kennytm kennytm removed the I-needs-decision Issue: In need of a decision. label Jan 7, 2018
@leoyvens
Copy link
Contributor Author

leoyvens commented Jan 8, 2018

@petrochenkov Alright, do we need it in HIR also, or can we error if we encounter it in lowering?

When the new versions of crossbeam get a sufficiently large share of the daily downloads in crates.io, perhaps we may reconsider completely dropping support for the old syntax.

@petrochenkov
Copy link
Contributor

petrochenkov commented Jan 8, 2018

@leodasvacas

Alright, do we need it in HIR also, or can we error if we encounter it in lowering?

No, no HIR, no pretty-printing support or anything, the single purpose of it is to report an error at some point (in AST validation or during lowering to HIR), after that it's no longer necessary.

@petrochenkov
Copy link
Contributor

petrochenkov commented Jan 10, 2018

@leodasvacas
Actually, could you use the name ItemKind::Err(ErrItemKind) for the new item? It's consistent with other similar "erroneous" fragments in AST and can be used for some other things in the future, not related to obsolescence.
Using and impl for TyKind::Err would be even simpler (no changes to AST).

@petrochenkov
Copy link
Contributor

@leodasvacas
I'd like to land this PR sooner.
I can rebase it and finish the parsing stuff if you don't have time.

@leoyvens
Copy link
Contributor Author

leoyvens commented Jan 13, 2018 via email

@petrochenkov
Copy link
Contributor

Closing in favor of #47416

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-lang Relevant to the language team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants