Skip to content

impl fn indented to left margin #36

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

Closed
hugoduncan opened this issue Feb 11, 2015 · 4 comments · Fixed by #38
Closed

impl fn indented to left margin #36

hugoduncan opened this issue Feb 11, 2015 · 4 comments · Fixed by #38

Comments

@hugoduncan
Copy link

Under some circumstances, impl functions, such as method_allows below, are indented to the left margin. I have tried to reduce this example further but have failed to reproduce the behaviour with anything simpler.

In some case indentation is also not fixed - invoking indent-for-tab-command several times results in toggling of indentation levels.

#[derive(RustcEncodable)]
struct Unit {
    name: String,
}
/// Handler for Units
#[derive(Debug,Clone)]
pub struct Units;
resource_handler!(Units);

impl Resource for Units {
    fn available_content_types(&self, _: &Request, _: &mut Response) -> Vec<Mime> {
        vec![Mime(TopLevel::Application, SubLevel::Json, vec![])]
    }

fn method_allowed(&self, req: &Request, _: &mut Response) -> Vec<Mime> {
        match req.method {
        method::Get|method::Head|method::Post => true,
        _ => false
        }
    }

    fn handle_ok(&self, _: &Request, resp: &mut Response) -> ResourceResult {
        "connection failed"
    }
}
@MicahChalmer
Copy link
Contributor

I tried to reproduce this and couldn't. For me, your code example indented as follows (which looks correct to me):

#[derive(RustcEncodable)]
struct Unit {
    name: String,
}
/// Handler for Units
#[derive(Debug,Clone)]
pub struct Units;
resource_handler!(Units);

impl Resource for Units {
    fn available_content_types(&self, _: &Request, _: &mut Response) -> Vec<Mime> {
        vec![Mime(TopLevel::Application, SubLevel::Json, vec![])]
    }

    fn method_allowed(&self, req: &Request, _: &mut Response) -> Vec<Mime> {
        match req.method {
            method::Get|method::Head|method::Post => true,
            _ => false
        }
    }

    fn handle_ok(&self, _: &Request, resp: &mut Response) -> ResourceResult {
        "connection failed"
    }
}

I tried it with emacs 24.4 and 23.4, both with my own usual emacs settings and with --no-init-file and no extra elisp loaded other than rust-mode.el. I wonder if there's some other setting that triggers the issue?

@hugoduncan
Copy link
Author

I'll try and track it down further. The behaviour started when the new raw string handling was introduced.

@MicahChalmer
Copy link
Contributor

I think I may have reproduced the issue. This code is an adapted snippet of a file in the rust tree (src/libstd/collections/hash/table.rs). Put it in a rust file by itself and indent it and usually it will start incorrectly pushing the indentation to the left somewhere in the middle. But, frustratingly, it's not the same place each time!

impl Foo for Bar {

    /// Modifies the bucket pointer in place to make it point to the next slot.
    pub fn next(&mut self) {
        // Branchless bucket
        // As we reach the end of the table...
        // We take the current idx:          0111111b
        // Xor it by its increment:        ^ 1000000b
        //                               ------------
        //                                   1111111b
        // Then AND with the capacity:     & 1000000b
        //                               ------------
        // to get the backwards offset:      1000000b
        let maybe_wraparound_dist = (self.idx ^ (self.idx + 1)) & self.table.capacity();
        // Finally, we obtain the offset 1 or the offset -cap + 1.
        let dist = 1 - (maybe_wraparound_dist as isize);

        self.idx += 1;

        unsafe {
            self.raw = self.raw.offset(dist);
        }
    }

    /// Reads a bucket at a given index, returning an enum indicating whether
    /// the appropriate types to call most of the other functions in
    /// this module.
    pub fn peek(self) -> wtF {
        match foo {
            EMPTY_BUCKET =>
                Empty(EmptyBucket {
                    raw: self.raw,
                    idx: self.idx,
                    table: self.table
                }),
            _ =>
                Full(FullBucket {
                    raw: self.raw,
                    idx: self.idx,
                    table: self.table
                })
        }
    }    
}

I know that the basic problem is that it starts getting confused about the paren level. At some point the syntax parsing starts returning 0 (meaning we are not inside any parens/brackets) even though it's still inside the impl. What I don't know is why. There isn't anything in the code that even trips the font-lock-syntactic-keywords regexps--there are neither single quotes nor double quotes in it!

Trying to debug it is even more frustrating because the behavior seems non-deterministic. Removing or changing lines can make the problem go away, but it seems to depend on what you tried beforehand.

I tried adding this snippet to an ERT test, figuring that at least if I restarted the process cleanly each time I would get consistent behavior and be able to simplify the example and narrow down the issue. Not so! If I run that test alone, it always succeeds. If I run it along with all the other tests (it ends up running last) it just about always fails.

So some sort of global state is being set in one of the other tests, causing this one to fail once the other one runs. I'll continue to try to track it down.

@vhbit
Copy link

vhbit commented Feb 15, 2015

@MicahChalmer, as I've mentioned in #30 - it happens for me pretty often, even if there is no impl involved like:

#[no_mangle]
pub extern fn foo(bar: c_int) -> c_int {
use util;
bar - 3
}

This code is extremely simple and in some cases works fine, so it looks like your assumption about corrupted state is true.

In my case I've got through bisecting that it started with 6b57bbf. You can check if tests work fine with prev commit, maybe it'll narrow search area.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants