about summary refs log tree commit diff
path: root/src/doc/rustc-dev-guide/examples
diff options
context:
space:
mode:
authorGeorge Fraser <george@fivetran.com>2020-05-05 21:41:11 -0700
committerWho? Me?! <mark-i-m@users.noreply.github.com>2020-05-07 17:30:27 -0500
commitd4de7a663d337f627252a6b7926422a9f7024968 (patch)
treeb14f46dbdd1e87a2e7f03fc91d6444e2393a012d /src/doc/rustc-dev-guide/examples
parentcdba65df35f2b51bc5e3ddf4c9678b0b06df4913 (diff)
downloadrust-d4de7a663d337f627252a6b7926422a9f7024968.tar.gz
rust-d4de7a663d337f627252a6b7926422a9f7024968.zip
Reference complete examples
Diffstat (limited to 'src/doc/rustc-dev-guide/examples')
-rw-r--r--src/doc/rustc-dev-guide/examples/rustc-driver-example.rs56
-rw-r--r--src/doc/rustc-dev-guide/examples/rustc-driver-getting-diagnostics.rs89
-rw-r--r--src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs78
3 files changed, 187 insertions, 36 deletions
diff --git a/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs b/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs
index 62c80b4aedb..4b0b23aaa52 100644
--- a/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs
+++ b/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs
@@ -1,17 +1,20 @@
 #![feature(rustc_private)]
 
+// NOTE: For the example to compile, you will need to first run the following:
+//   rustup component add rustc-dev
+
 extern crate rustc;
 extern crate rustc_error_codes;
 extern crate rustc_errors;
 extern crate rustc_hash;
 extern crate rustc_hir;
 extern crate rustc_interface;
+extern crate rustc_session;
 extern crate rustc_span;
 
-use rustc::session;
-use rustc::session::config;
 use rustc_errors::registry;
 use rustc_hash::{FxHashMap, FxHashSet};
+use rustc_session::config;
 use rustc_span::source_map;
 use std::path;
 use std::process;
@@ -24,60 +27,41 @@ fn main() {
         .output()
         .unwrap();
     let sysroot = str::from_utf8(&out.stdout).unwrap().trim();
-    let filename = "main.rs";
-    let contents = "static HELLO: &str = \"Hello, world!\"; fn main() { println!(\"{}\", HELLO); }";
-    let errors = registry::Registry::new(&rustc_error_codes::DIAGNOSTICS);
     let config = rustc_interface::Config {
         // Command line options
         opts: config::Options {
             maybe_sysroot: Some(path::PathBuf::from(sysroot)),
             ..config::Options::default()
         },
-
         // cfg! configuration in addition to the default ones
-        // FxHashSet<(String, Option<String>)>
-        crate_cfg: FxHashSet::default(),
-
+        crate_cfg: FxHashSet::default(), // FxHashSet<(String, Option<String>)>
         input: config::Input::Str {
-            name: source_map::FileName::Custom(String::from(filename)),
-            input: String::from(contents),
+            name: source_map::FileName::Custom("main.rs".to_string()),
+            input: "static HELLO: &str = \"Hello, world!\"; fn main() { println!(\"{}\", HELLO); }"
+                .to_string(),
         },
-        // Option<PathBuf>
-        input_path: None,
-        // Option<PathBuf>
-        output_dir: None,
-        // Option<PathBuf>
-        output_file: None,
-        // Option<Box<dyn FileLoader + Send + Sync>>
-        file_loader: None,
-        diagnostic_output: session::DiagnosticOutput::Default,
-
+        input_path: None,  // Option<PathBuf>
+        output_dir: None,  // Option<PathBuf>
+        output_file: None, // Option<PathBuf>
+        file_loader: None, // Option<Box<dyn FileLoader + Send + Sync>>
+        diagnostic_output: rustc_session::DiagnosticOutput::Default,
         // Set to capture stderr output during compiler execution
-        // Option<Arc<Mutex<Vec<u8>>>>
-        stderr: None,
-
-        // Option<String>
-        crate_name: None,
-        // FxHashMap<lint::LintId, lint::Level>
-        lint_caps: FxHashMap::default(),
-
+        stderr: None,                    // Option<Arc<Mutex<Vec<u8>>>>
+        crate_name: None,                // Option<String>
+        lint_caps: FxHashMap::default(), // FxHashMap<lint::LintId, lint::Level>
         // This is a callback from the driver that is called when we're registering lints;
         // it is called during plugin registration when we have the LintStore in a non-shared state.
         //
         // Note that if you find a Some here you probably want to call that function in the new
         // function being registered.
-        // Option<Box<dyn Fn(&Session, &mut LintStore) + Send + Sync>>
-        register_lints: None,
-
+        register_lints: None, // Option<Box<dyn Fn(&Session, &mut LintStore) + Send + Sync>>
         // This is a callback from the driver that is called just after we have populated
         // the list of queries.
         //
         // The second parameter is local providers and the third parameter is external providers.
-        // Option<fn(&Session, &mut ty::query::Providers<'_>, &mut ty::query::Providers<'_>)>
-        override_queries: None,
-
+        override_queries: None, // Option<fn(&Session, &mut ty::query::Providers<'_>, &mut ty::query::Providers<'_>)>
         // Registry of diagnostics codes.
-        registry: errors,
+        registry: registry::Registry::new(&rustc_error_codes::DIAGNOSTICS),
     };
     rustc_interface::run_compiler(config, |compiler| {
         compiler.enter(|queries| {
diff --git a/src/doc/rustc-dev-guide/examples/rustc-driver-getting-diagnostics.rs b/src/doc/rustc-dev-guide/examples/rustc-driver-getting-diagnostics.rs
new file mode 100644
index 00000000000..cf08ed87fc3
--- /dev/null
+++ b/src/doc/rustc-dev-guide/examples/rustc-driver-getting-diagnostics.rs
@@ -0,0 +1,89 @@
+#![feature(rustc_private)]
+
+// NOTE: For the example to compile, you will need to first run the following:
+//   rustup component add rustc-dev
+
+extern crate rustc;
+extern crate rustc_error_codes;
+extern crate rustc_errors;
+extern crate rustc_hash;
+extern crate rustc_hir;
+extern crate rustc_interface;
+extern crate rustc_session;
+extern crate rustc_span;
+
+use rustc_errors::registry;
+use rustc_session::config;
+use rustc_span::source_map;
+use std::io;
+use std::path;
+use std::process;
+use std::str;
+use std::sync;
+
+// Buffer diagnostics in a Vec<u8>.
+#[derive(Clone)]
+pub struct DiagnosticSink(sync::Arc<sync::Mutex<Vec<u8>>>);
+
+impl io::Write for DiagnosticSink {
+    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+        self.0.lock().unwrap().write(buf)
+    }
+    fn flush(&mut self) -> io::Result<()> {
+        self.0.lock().unwrap().flush()
+    }
+}
+
+fn main() {
+    let out = process::Command::new("rustc")
+        .arg("--print=sysroot")
+        .current_dir(".")
+        .output()
+        .unwrap();
+    let sysroot = str::from_utf8(&out.stdout).unwrap().trim();
+    let buffer = sync::Arc::new(sync::Mutex::new(Vec::new()));
+    let config = rustc_interface::Config {
+        opts: config::Options {
+            maybe_sysroot: Some(path::PathBuf::from(sysroot)),
+            // Configure the compiler to emit diagnostics in compact JSON format.
+            error_format: config::ErrorOutputType::Json {
+                pretty: false,
+                json_rendered: rustc_errors::emitter::HumanReadableErrorType::Default(
+                    rustc_errors::emitter::ColorConfig::Never,
+                ),
+            },
+            ..config::Options::default()
+        },
+        // This program contains a type error.
+        input: config::Input::Str {
+            name: source_map::FileName::Custom("main.rs".to_string()),
+            input: "fn main() { let x: &str = 1; }".to_string(),
+        },
+        // Redirect the diagnostic output of the compiler to a buffer.
+        diagnostic_output: rustc_session::DiagnosticOutput::Raw(Box::from(DiagnosticSink(
+            buffer.clone(),
+        ))),
+        crate_cfg: rustc_hash::FxHashSet::default(),
+        input_path: None,
+        output_dir: None,
+        output_file: None,
+        file_loader: None,
+        stderr: None,
+        crate_name: None,
+        lint_caps: rustc_hash::FxHashMap::default(),
+        register_lints: None,
+        override_queries: None,
+        registry: registry::Registry::new(&rustc_error_codes::DIAGNOSTICS),
+    };
+    rustc_interface::run_compiler(config, |compiler| {
+        compiler.enter(|queries| {
+            queries.global_ctxt().unwrap().take().enter(|tcx| {
+                // Run the analysis phase on the local crate to trigger the type error.
+                tcx.analysis(rustc_hir::def_id::LOCAL_CRATE);
+            });
+        });
+    });
+    // Read buffered diagnostics.
+    let diagnostics = String::from_utf8(buffer.lock().unwrap().clone()).unwrap();
+    println!("{}", diagnostics);
+}
diff --git a/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs b/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs
new file mode 100644
index 00000000000..105ee00194e
--- /dev/null
+++ b/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs
@@ -0,0 +1,78 @@
+#![feature(rustc_private)]
+
+// NOTE: For the example to compile, you will need to first run the following:
+//   rustup component add rustc-dev
+
+extern crate rustc;
+extern crate rustc_error_codes;
+extern crate rustc_errors;
+extern crate rustc_hash;
+extern crate rustc_hir;
+extern crate rustc_interface;
+extern crate rustc_session;
+extern crate rustc_span;
+
+use rustc_errors::registry;
+use rustc_session::config;
+use rustc_span::source_map;
+use std::path;
+use std::process;
+use std::str;
+
+fn main() {
+    let out = process::Command::new("rustc")
+        .arg("--print=sysroot")
+        .current_dir(".")
+        .output()
+        .unwrap();
+    let sysroot = str::from_utf8(&out.stdout).unwrap().trim();
+    let config = rustc_interface::Config {
+        opts: config::Options {
+            maybe_sysroot: Some(path::PathBuf::from(sysroot)),
+            ..config::Options::default()
+        },
+        input: config::Input::Str {
+            name: source_map::FileName::Custom("main.rs".to_string()),
+            input: "fn main() { let message = \"Hello, world!\"; println!(\"{}\", message); }"
+                .to_string(),
+        },
+        diagnostic_output: rustc_session::DiagnosticOutput::Default,
+        crate_cfg: rustc_hash::FxHashSet::default(),
+        input_path: None,
+        output_dir: None,
+        output_file: None,
+        file_loader: None,
+        stderr: None,
+        crate_name: None,
+        lint_caps: rustc_hash::FxHashMap::default(),
+        register_lints: None,
+        override_queries: None,
+        registry: registry::Registry::new(&rustc_error_codes::DIAGNOSTICS),
+    };
+    rustc_interface::run_compiler(config, |compiler| {
+        compiler.enter(|queries| {
+            // Analyze the crate and inspect the types under the cursor.
+            queries.global_ctxt().unwrap().take().enter(|tcx| {
+                // Every compilation contains a single crate.
+                let krate = tcx.hir().krate();
+                // Iterate over the top-level items in the crate, looking for the main function.
+                for (_, item) in &krate.items {
+                    // Use pattern-matching to find a specific node inside the main function.
+                    if let rustc_hir::ItemKind::Fn(_, _, body_id) = item.kind {
+                        let expr = &tcx.hir().body(body_id).value;
+                        if let rustc_hir::ExprKind::Block(block, _) = expr.kind {
+                            if let rustc_hir::StmtKind::Local(local) = block.stmts[0].kind {
+                                if let Some(expr) = local.init {
+                                    let hir_id = expr.hir_id; // hir_id identifies the string "Hello, world!"
+                                    let def_id = tcx.hir().local_def_id(item.hir_id); // def_id identifies the main function
+                                    let ty = tcx.typeck_tables_of(def_id).node_type(hir_id);
+                                    println!("{:?}: {:?}", expr, ty); // prints expr(HirId { owner: DefIndex(3), local_id: 4 }: "Hello, world!"): &'static str
+                                }
+                            }
+                        }
+                    }
+                }
+            })
+        });
+    });
+}