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

Prohibit parenthesized params in more types. #41856

Merged

Conversation

qnighy
Copy link
Contributor

@qnighy qnighy commented May 9, 2017

Prohibit parenthesized parameters in primitive types, type parameters, Self, etc.

Fixes #32995.

@rust-highfive
Copy link
Collaborator

Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @arielb1 (or someone else) soon.

If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. Due to the way GitHub handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes.

Please see the contribution instructions for more information.

@arielb1 arielb1 added the S-waiting-on-crater Status: Waiting on a crater run to be completed. label May 9, 2017
@TimNN
Copy link
Contributor

TimNN commented May 10, 2017

Hi @qnighy, thanks for the PR! We'll regularly check in to make sure that @arielb1 or someone else from the team reviews this soon.

@TimNN TimNN added the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label May 10, 2017
@qnighy
Copy link
Contributor Author

qnighy commented May 12, 2017

@TimNN thanks for response too! So now I can just wait for review, right? I'm just confused about the meaning of "S-waiting-on-author".

@arielb1
Copy link
Contributor

arielb1 commented May 12, 2017

Sorry for being late on review.

There's another case here: https://github.com/qnighy/rust/blob/63ecd6aa0f2c8a6807528d8bdf5eb30211b3fcd4/src/librustc_typeck/astconv.rs#L1395

Example test case:

use std::fmt::Display;

fn main() {
    let s: Box<Display+std<Display>::marker::Sync()> = Box::new(2);
}

Basically every time we access segments we want to make sure they have the correct form.

@qnighy
Copy link
Contributor Author

qnighy commented May 13, 2017

Thanks for reviewing, and I found another case which leads to ICE.

macro_rules! pathexpr {
    ($p:path) => ($p);
}
fn main() {
    println!("{}", pathexpr!(std::str::from_utf8())(b"Hello").unwrap());
}
error: internal compiler error: src/librustc_typeck/check/mod.rs:4498: parenthesized parameters cannot appear in ExprPath
 --> test.rs:2:19
  |
2 |     ($p:path) => ($p);
  |                   ^^
...
5 |     println!("{}", pathexpr!(std::str::from_utf8())(b"Hello").unwrap());
  |                    -------------------------------- in this macro invocation

@qnighy
Copy link
Contributor Author

qnighy commented May 13, 2017

In summary, we'll have to additionally deal with

  • ICE for () appearing in expression-like path
  • () in module path for bounds, trait objects and impls
  • Send/Sync bound for trait objects
macro_rules! pathexpr {
    (($($x:tt)*), $p:path, ($($y:tt)*)) => ($($x)* $p $($y)*);
}

mod m1 {
    pub struct A {}
    pub struct B();
    pub struct C;
    pub trait Marker {}
}

trait Tr {
    type A;
    type B;
    type C;
    fn f();
}

struct D;
impl Tr for D {
    type A = m1::A;
    type B = m1::B;
    type C = m1::C;
    fn f() {}
}

// ItemUse
// pathexpr!((use), std::boxed()::Box, (;)); // ERROR from ast_validation

// Visibility
mod m2 {
    macro_rules! foo {
        ($p:path) => { pub(in $p) mod mm {} }
    }
    // foo!(m2()); // ERROR from ast_validation
}

fn main() {
    // QPath::Resolved in PatKind::Struct
    // let pathexpr!((), m1()::A , ({})) = m1::A {}; // ERROR from astconv
    // let pathexpr!((), m1::A() , ({})) = m1::A {}; // ERROR from astconv

    // QPath::Resolved in PatKind::TupleStruct
    // let pathexpr!((), m1()::B , (())) = m1::B(); // ERROR from astconv
    // let pathexpr!((), m1::B() , (())) = m1::B(); // ICE

    // QPath::Resolved in PatKind::Path
    // let pathexpr!((), m1()::C , ()) = m1::C; // ERROR from astconv
    // let pathexpr!((), m1::C() , ()) = m1::C; // ICE

    // QPath::Resolved in ExprPath
    // pathexpr!((), m1()::C, ()); // ERROR from astconv
    // pathexpr!((), m1::C(), ()); // ICE

    // QPath::Resolved in ExprStruct
    // pathexpr!((), m1()::A, ({})); // ERROR from astconv
    // pathexpr!((), m1::A(), ({})); // ERROR from astconv

    // QPath::Resolved in TyPath
    // let _ : m1()::C = m1::C; // ERROR from astconv
    // let _ : m1::C() = m1::C; // ERROR from astconv

    // QPath::TypeRelative in PatKind::Struct
    // let pathexpr!((), D::A(), ({})) = m1::A {}; // ERROR from astconv

    // QPath::TypeRelative in PatKind::TupleStruct
    // let pathexpr!((), D::B(), (())) = m1::B (); // resolution error

    // QPath::TypeRelative in PatKind::Path
    // let pathexpr!((), D::C, ()) = m1::C; // resolution error

    // QPath::TypeRelative in ExprPath
    // pathexpr!((), D::f(), ()); // ICE

    // QPath::TypeRelative in ExprStruct
    // pathexpr!((), D::A(), ({})); // ERROR from astconv

    // QPath::TypeRelative in TyPath
    // let _ : D::C() = m1::C; // ERROR from astconv

    // TraitTyParamBound
    { fn f<X: m1()::Marker>() {} }
    // { fn f<X: m1::Marker()>() {} } // type error

    // TyTraitObject
    let x : &m1()::Marker;
    // let x : &m1::Marker(); // type error
    let x : &(m1::Marker + Sync());

    // ItemDefaultImpl: omitted

    // ItemImpl
    impl m1()::Marker for u32 {}
    // impl m1::Marker() for i32 {} // type error
}

@qnighy
Copy link
Contributor Author

qnighy commented May 15, 2017

Dealt with all path segments I found so far.

@arielb1
Copy link
Contributor

arielb1 commented May 15, 2017

@bors r+

@bors
Copy link
Contributor

bors commented May 15, 2017

📌 Commit 2a20073 has been approved by arielb1

@bors
Copy link
Contributor

bors commented May 15, 2017

⌛ Testing commit 2a20073 with merge a89314f...

@bors
Copy link
Contributor

bors commented May 15, 2017

💔 Test failed - status-appveyor

@qnighy
Copy link
Contributor Author

qnighy commented May 15, 2017

Oh, this is the first failure for my PR to rust-lang... It is a spurious failure, I suppose?

@petrochenkov
Copy link
Contributor

Yeah, it's spurious, should be mitigated by #41996
@bors retry

frewsxcv added a commit to frewsxcv/rust that referenced this pull request May 15, 2017
…s-in-more-types, r=arielb1

Prohibit parenthesized params in more types.

Prohibit parenthesized parameters in primitive types, type parameters, `Self`, etc.

Fixes rust-lang#32995.
@frewsxcv
Copy link
Member

@bors r-

this hit an error on travis https://travis-ci.org/rust-lang/rust/jobs/232310581

@qnighy
Copy link
Contributor Author

qnighy commented May 16, 2017

An existing compile-fail test hit a newly introduced error.

This time I ran all tests and it should be fixed.

@Mark-Simulacrum
Copy link
Member

@bors r=arielb1

@bors
Copy link
Contributor

bors commented May 16, 2017

📌 Commit e8137d7 has been approved by arielb1

@bors
Copy link
Contributor

bors commented May 16, 2017

⌛ Testing commit e8137d7 with merge 0915d89...

bors added a commit that referenced this pull request May 16, 2017
…ypes, r=arielb1

Prohibit parenthesized params in more types.

Prohibit parenthesized parameters in primitive types, type parameters, `Self`, etc.

Fixes #32995.
@Mark-Simulacrum
Copy link
Member

@bors r-
@bors retry

This needed a crater run, and I don't think that happened.

@qnighy
Copy link
Contributor Author

qnighy commented May 16, 2017

@Mark-Simulacrum I suppose no. Is that what I can do by myself?

@brson
Copy link
Contributor

brson commented May 25, 2017

I've started the crate build.

@brson
Copy link
Contributor

brson commented May 25, 2017

@Mark-Simulacrum
Copy link
Member

Actual root regressions. All look "intentional" though none seem needed for any reason.

@nikomatsakis
Copy link
Contributor

Looks like these are legit -- I think we need a warning cycle. @qnighy, a rough description of the procedure for warning cycles is described here on forge.

@petrochenkov
Copy link
Contributor

I can't believe people actually write this.
How does that happen? There should be some explanation.

@qnighy
Copy link
Contributor Author

qnighy commented May 26, 2017

OK, I'll try it. I didn't expect this is actually exploited in several libraries.

@qnighy
Copy link
Contributor Author

qnighy commented May 26, 2017

This PR now have two changes:

  1. Prohibit parenthesized parameters () where angle-bracketed parameters <T> are already prohibited.
  2. Prohibit parameters of any kind () (T) <T> where even <T> was not checked.

It seems that only the former one hit regressions. Is it sufficient to only prepare a warning cycle for the former one?

@qnighy
Copy link
Contributor Author

qnighy commented May 26, 2017

Prepared the tracking issue for the warning cycle: #42238

@qnighy
Copy link
Contributor Author

qnighy commented May 26, 2017

Added the warning cycle. I wonder if this is sufficient?

@shepmaster
Copy link
Member

I can't believe people actually write this.
How does that happen? There should be some explanation.

@petrochenkov I can only speak for my own crate, but my guess is that I did some copy-pasta when implementing size_hint and count, and just ended up with some rogue parens that didn't hurt anything.

@arielb1
Copy link
Contributor

arielb1 commented May 29, 2017

Do we do another crater run then? r+ modulo that.

@arielb1
Copy link
Contributor

arielb1 commented May 29, 2017

Well, let's go

@bors r+

@bors
Copy link
Contributor

bors commented May 29, 2017

📌 Commit 9999378 has been approved by arielb1

@bors
Copy link
Contributor

bors commented May 29, 2017

⌛ Testing commit 9999378 with merge 03bed65...

bors added a commit that referenced this pull request May 29, 2017
…ypes, r=arielb1

Prohibit parenthesized params in more types.

Prohibit parenthesized parameters in primitive types, type parameters, `Self`, etc.

Fixes #32995.
@qnighy
Copy link
Contributor Author

qnighy commented May 29, 2017

Could anyone tag the tracking issue 42292 #42238 with B-unstable and T-compiler?

@Mark-Simulacrum
Copy link
Member

Added tags to #42238; the issue you referenced doesn't appear to be the right tracking issue.

@qnighy
Copy link
Contributor Author

qnighy commented May 29, 2017

Thank you, that was just my mistake.

@bors
Copy link
Contributor

bors commented May 29, 2017

☀️ Test successful - status-appveyor, status-travis
Approved by: arielb1
Pushing 03bed65 to master...

@bors bors merged commit 9999378 into rust-lang:master May 29, 2017
@qnighy qnighy deleted the prohibit-parenthesized-params-in-more-types branch May 29, 2017 23:53
@qnighy
Copy link
Contributor Author

qnighy commented May 29, 2017

Thank you all for reviewing!

bors added a commit that referenced this pull request Aug 21, 2017
syntax: Relax path grammar

TLDR: Accept the disambiguator `::` in "type" paths (`Type::<Args>`), accept the disambiguator `::` before parenthesized generic arguments (`Fn::(Args)`).

The "turbofish" disambiguator `::<>` in expression paths is a necessary evil required for path parsing to be both simple and to give reasonable results.
Since paths in expressions usually refer to values (but not necessarily, e.g. `Struct::<u8> { field: 0 }` is disambiguated, but refers to a type), people often consider `::<>` to be inherent to *values*, and not *expressions* and want to write disambiguated paths for values even in contexts where disambiguation is not strictly necessary, for example when a path is passed to a macro `m!(Vec::<i32>::new)`.
The problem is that currently, if the disambiguator is not *required*, then it's *prohibited*. This results in confusion - see #41740, https://internals.rust-lang.org/t/macro-path-uses-novel-syntax/5561.

This PR makes the disambiguator *optional* instead of prohibited in contexts where it's not strictly required, so people can pass paths to macros in whatever form they consider natural (e.g. disambiguated form for value paths).
This PR also accepts the disambiguator in paths with parenthesized arguments (`Fn::(Args)`) for consistency and to simplify testing of stuff like #41856 (comment).

Closes #41740

cc @rust-lang/lang
r? @nikomatsakis
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-crater Status: Waiting on a crater run to be completed. S-waiting-on-team Status: Awaiting decision from the relevant subteam (see the T-<team> label). T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.