summaryrefslogtreecommitdiff
path: root/tests/ui/impl-trait/defining-use-uncaptured-non-universal-region-2.rs
blob: 56e099c28d2193c2e7682d93f2ac4a1eef24f97b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// issue: #110623
//@ check-pass

use std::{collections::BTreeMap, num::ParseIntError, str::FromStr};

enum FileSystem {
    File(usize),
    Directory(BTreeMap<String, FileSystem>),
}

impl FromStr for FileSystem {
    type Err = ParseIntError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if s.starts_with("dir") {
            Ok(Self::new_dir())
        } else {
            Ok(Self::File(s.split_whitespace().next().unwrap().parse()?))
        }
    }
}

impl FileSystem {
    fn new_dir() -> FileSystem {
        FileSystem::Directory(BTreeMap::new())
    }

    fn insert(&mut self, name: String, other: FileSystem) -> Option<FileSystem> {
        match self {
            FileSystem::File(_) => panic!("can only insert into directory!"),
            FileSystem::Directory(tree) => tree.insert(name, other),
        }
    }

    // Recursively build a tree from commands. This uses (abuses?)
    // the fact that `cd /` only appears at the start and that
    // subsequent `cd`s can only move ONE level to use the recursion
    // stack as the filesystem stack
    fn build<'a>(
        &mut self,
        mut commands: impl Iterator<Item = &'a str> + 'a,
    ) -> Option<impl Iterator<Item = &'a str> + 'a> {
        let cmd = commands.next()?;
        let mut elements = cmd.lines();
        match elements.next().map(str::trim) {
            Some("cd /") | None => self.build(commands),
            Some("cd ..") => {
                // return to higher scope
                Some(commands)
            }
            Some("ls") => {
                for item in elements {
                    let name = item.split_whitespace().last().unwrap();
                    let prior = self.insert(name.to_string(), item.parse().unwrap());
                    debug_assert!(prior.is_none());
                }
                // continue on
                self.build(commands)
            }
            Some(other_cd) => {
                let name = other_cd
                    .trim()
                    .strip_prefix("cd ")
                    .expect("expected a cd command");
                let mut directory = FileSystem::new_dir();
                let further_commands = directory.build(commands);
                self.insert(name.to_string(), directory);
                self.build(further_commands?) // THIS LINE FAILS TO COMPILE
            }
        }
    }
}

fn main() {}