From ad2b4f44412391ff14d96d71d7b6a212f1d94755 Mon Sep 17 00:00:00 2001 From: Vytautas Astrauskas Date: Thu, 24 Jun 2021 13:34:17 +0200 Subject: [PATCH 1/7] Enable compiler consumers to obtain Body with Polonius facts. --- .../rustc_mir/src/borrow_check/consumers.rs | 28 +++++++++ compiler/rustc_mir/src/borrow_check/facts.rs | 4 +- .../rustc_mir/src/borrow_check/location.rs | 12 ++-- compiler/rustc_mir/src/borrow_check/mod.rs | 58 ++++++++++++++++--- compiler/rustc_mir/src/borrow_check/nll.rs | 6 +- compiler/rustc_mir/src/lib.rs | 3 + 6 files changed, 94 insertions(+), 17 deletions(-) create mode 100644 compiler/rustc_mir/src/borrow_check/consumers.rs diff --git a/compiler/rustc_mir/src/borrow_check/consumers.rs b/compiler/rustc_mir/src/borrow_check/consumers.rs new file mode 100644 index 0000000000000..28c2c750136ca --- /dev/null +++ b/compiler/rustc_mir/src/borrow_check/consumers.rs @@ -0,0 +1,28 @@ +//! This file provides API for compiler consumers. + +use rustc_hir::def_id::LocalDefId; +use rustc_index::vec::IndexVec; +use rustc_infer::infer::TyCtxtInferExt; +use rustc_middle::mir::Body; +use rustc_middle::ty::{self, TyCtxt}; + +pub use super::{ + facts::{AllFacts as PoloniusInput, RustcFacts}, + location::{LocationTable, RichLocation}, + nll::PoloniusOutput, + BodyWithBorrowckFacts, +}; + +/// This function computes Polonius facts for the given body. It makes a copy of +/// the body because it needs to regenerate the region identifiers. +pub fn get_body_with_borrowck_facts<'tcx>( + tcx: TyCtxt<'tcx>, + def: ty::WithOptConstParam, +) -> BodyWithBorrowckFacts<'tcx> { + let (input_body, promoted) = tcx.mir_promoted(def); + tcx.infer_ctxt().enter(|infcx| { + let input_body: &Body<'_> = &input_body.borrow(); + let promoted: &IndexVec<_, _> = &promoted.borrow(); + *super::do_mir_borrowck(&infcx, input_body, promoted, true).1.unwrap() + }) +} diff --git a/compiler/rustc_mir/src/borrow_check/facts.rs b/compiler/rustc_mir/src/borrow_check/facts.rs index 6d6b94ecf6440..daea5e538ed51 100644 --- a/compiler/rustc_mir/src/borrow_check/facts.rs +++ b/compiler/rustc_mir/src/borrow_check/facts.rs @@ -12,7 +12,7 @@ use std::io::{BufWriter, Write}; use std::path::Path; #[derive(Copy, Clone, Debug)] -crate struct RustcFacts; +pub struct RustcFacts; impl polonius_engine::FactTypes for RustcFacts { type Origin = RegionVid; @@ -22,7 +22,7 @@ impl polonius_engine::FactTypes for RustcFacts { type Path = MovePathIndex; } -crate type AllFacts = PoloniusFacts; +pub type AllFacts = PoloniusFacts; crate trait AllFactsExt { /// Returns `true` if there is a need to gather `AllFacts` given the diff --git a/compiler/rustc_mir/src/borrow_check/location.rs b/compiler/rustc_mir/src/borrow_check/location.rs index 375ff72679f8f..d378a2cbea3e1 100644 --- a/compiler/rustc_mir/src/borrow_check/location.rs +++ b/compiler/rustc_mir/src/borrow_check/location.rs @@ -12,7 +12,7 @@ use rustc_middle::mir::{BasicBlock, Body, Location}; /// granularity through outlives relations; however, the rich location /// table serves another purpose: it compresses locations from /// multiple words into a single u32. -crate struct LocationTable { +pub struct LocationTable { num_points: usize, statements_before_block: IndexVec, } @@ -24,7 +24,7 @@ rustc_index::newtype_index! { } #[derive(Copy, Clone, Debug)] -crate enum RichLocation { +pub enum RichLocation { Start(Location), Mid(Location), } @@ -48,23 +48,23 @@ impl LocationTable { Self { num_points, statements_before_block } } - crate fn all_points(&self) -> impl Iterator { + pub fn all_points(&self) -> impl Iterator { (0..self.num_points).map(LocationIndex::new) } - crate fn start_index(&self, location: Location) -> LocationIndex { + pub fn start_index(&self, location: Location) -> LocationIndex { let Location { block, statement_index } = location; let start_index = self.statements_before_block[block]; LocationIndex::new(start_index + statement_index * 2) } - crate fn mid_index(&self, location: Location) -> LocationIndex { + pub fn mid_index(&self, location: Location) -> LocationIndex { let Location { block, statement_index } = location; let start_index = self.statements_before_block[block]; LocationIndex::new(start_index + statement_index * 2 + 1) } - crate fn to_location(&self, index: LocationIndex) -> RichLocation { + pub fn to_location(&self, index: LocationIndex) -> RichLocation { let point_index = index.index(); // Find the basic block. We have a vector with the diff --git a/compiler/rustc_mir/src/borrow_check/mod.rs b/compiler/rustc_mir/src/borrow_check/mod.rs index 36eb8a4baa830..bda1c48e7658f 100644 --- a/compiler/rustc_mir/src/borrow_check/mod.rs +++ b/compiler/rustc_mir/src/borrow_check/mod.rs @@ -42,12 +42,14 @@ use self::diagnostics::{AccessKind, RegionName}; use self::location::LocationTable; use self::prefixes::PrefixSet; use self::MutateMode::{JustWrite, WriteAndRead}; +use facts::AllFacts; use self::path_utils::*; mod borrow_set; mod constraint_generation; mod constraints; +pub mod consumers; mod def_use; mod diagnostics; mod facts; @@ -108,22 +110,33 @@ fn mir_borrowck<'tcx>( let opt_closure_req = tcx.infer_ctxt().enter(|infcx| { let input_body: &Body<'_> = &input_body.borrow(); let promoted: &IndexVec<_, _> = &promoted.borrow(); - do_mir_borrowck(&infcx, input_body, promoted) + do_mir_borrowck(&infcx, input_body, promoted, false).0 }); debug!("mir_borrowck done"); tcx.arena.alloc(opt_closure_req) } +/// Perform the actual borrow checking. +/// +/// If `return_body_with_facts` is true, then return the body with non-erased +/// region ids on which the borrow checking was performed together with Polonius +/// facts. fn do_mir_borrowck<'a, 'tcx>( infcx: &InferCtxt<'a, 'tcx>, input_body: &Body<'tcx>, input_promoted: &IndexVec>, -) -> BorrowCheckResult<'tcx> { + return_body_with_facts: bool, +) -> (BorrowCheckResult<'tcx>, Option>>) { let def = input_body.source.with_opt_param().as_local().unwrap(); debug!("do_mir_borrowck(def = {:?})", def); + assert!( + !return_body_with_facts || infcx.tcx.sess.opts.debugging_opts.polonius, + "borrowck facts can be requested only when Polonius is enabled" + ); + let tcx = infcx.tcx; let param_env = tcx.param_env(def.did); let id = tcx.hir().local_def_id_to_hir_id(def.did); @@ -169,12 +182,14 @@ fn do_mir_borrowck<'a, 'tcx>( // requires first making our own copy of the MIR. This copy will // be modified (in place) to contain non-lexical lifetimes. It // will have a lifetime tied to the inference context. - let mut body = input_body.clone(); + let mut body_owned = input_body.clone(); let mut promoted = input_promoted.clone(); - let free_regions = nll::replace_regions_in_mir(infcx, param_env, &mut body, &mut promoted); - let body = &body; // no further changes + let free_regions = + nll::replace_regions_in_mir(infcx, param_env, &mut body_owned, &mut promoted); + let body = &body_owned; // no further changes - let location_table = &LocationTable::new(&body); + let location_table_owned = LocationTable::new(body); + let location_table = &location_table_owned; let mut errors_buffer = Vec::new(); let (move_data, move_errors): (MoveData<'tcx>, Vec<(Place<'tcx>, MoveError<'tcx>)>) = @@ -202,6 +217,7 @@ fn do_mir_borrowck<'a, 'tcx>( let nll::NllOutput { regioncx, opaque_type_values, + polonius_input, polonius_output, opt_closure_req, nll_errors, @@ -446,9 +462,37 @@ fn do_mir_borrowck<'a, 'tcx>( used_mut_upvars: mbcx.used_mut_upvars, }; + let body_with_facts = if return_body_with_facts { + let output_facts = mbcx.polonius_output.expect("Polonius output was not computed"); + Some(box BodyWithBorrowckFacts { + body: body_owned, + input_facts: *polonius_input.expect("Polonius input facts were not generated"), + output_facts, + location_table: location_table_owned, + }) + } else { + None + }; + debug!("do_mir_borrowck: result = {:#?}", result); - result + (result, body_with_facts) +} + +/// A `Body` with information computed by the borrow checker. This struct is +/// intended to be consumed by compiler consumers. +/// +/// We need to include the MIR body here because the region identifiers must +/// match the ones in the Polonius facts. +pub struct BodyWithBorrowckFacts<'tcx> { + /// A mir body that contains region identifiers. + pub body: Body<'tcx>, + /// Polonius input facts. + pub input_facts: AllFacts, + /// Polonius output facts. + pub output_facts: Rc, + /// The table that maps Polonius points to locations in the table. + pub location_table: LocationTable, } crate struct MirBorrowckCtxt<'cx, 'tcx> { diff --git a/compiler/rustc_mir/src/borrow_check/nll.rs b/compiler/rustc_mir/src/borrow_check/nll.rs index bfeafa33a91cf..7742b76d9a48b 100644 --- a/compiler/rustc_mir/src/borrow_check/nll.rs +++ b/compiler/rustc_mir/src/borrow_check/nll.rs @@ -40,13 +40,14 @@ use crate::borrow_check::{ Upvar, }; -crate type PoloniusOutput = Output; +pub type PoloniusOutput = Output; /// The output of `nll::compute_regions`. This includes the computed `RegionInferenceContext`, any /// closure requirements to propagate, and any generated errors. crate struct NllOutput<'tcx> { pub regioncx: RegionInferenceContext<'tcx>, pub opaque_type_values: VecMap, Ty<'tcx>>, + pub polonius_input: Option>, pub polonius_output: Option>, pub opt_closure_req: Option>, pub nll_errors: RegionErrors<'tcx>, @@ -271,7 +272,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( let def_id = body.source.def_id(); // Dump facts if requested. - let polonius_output = all_facts.and_then(|all_facts| { + let polonius_output = all_facts.as_ref().and_then(|all_facts| { if infcx.tcx.sess.opts.debugging_opts.nll_facts { let def_path = infcx.tcx.def_path(def_id); let dir_path = PathBuf::from(&infcx.tcx.sess.opts.debugging_opts.nll_facts_dir) @@ -305,6 +306,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( NllOutput { regioncx, opaque_type_values: remapped_opaque_tys, + polonius_input: all_facts.map(Box::new), polonius_output, opt_closure_req: closure_region_requirements, nll_errors, diff --git a/compiler/rustc_mir/src/lib.rs b/compiler/rustc_mir/src/lib.rs index a58ded9cfd3a4..5fb37b1b372ca 100644 --- a/compiler/rustc_mir/src/lib.rs +++ b/compiler/rustc_mir/src/lib.rs @@ -46,6 +46,9 @@ mod shim; pub mod transform; pub mod util; +// A public API provided for the Rust compiler consumers. +pub use self::borrow_check::consumers; + use rustc_middle::ty::query::Providers; pub fn provide(providers: &mut Providers) { From b913a4591a01424a2ff7fc47c8fd0e18ac0352e0 Mon Sep 17 00:00:00 2001 From: Vytautas Astrauskas Date: Thu, 22 Jul 2021 21:56:33 +0200 Subject: [PATCH 2/7] Add a test for get_body_with_borrowck_facts. --- .../rustc_mir/src/borrow_check/consumers.rs | 9 + src/test/run-make/obtain-borrowck/Makefile | 25 +++ src/test/run-make/obtain-borrowck/driver.rs | 171 ++++++++++++++++++ .../run-make/obtain-borrowck/output.stdout | 8 + src/test/run-make/obtain-borrowck/test.rs | 32 ++++ 5 files changed, 245 insertions(+) create mode 100644 src/test/run-make/obtain-borrowck/Makefile create mode 100644 src/test/run-make/obtain-borrowck/driver.rs create mode 100644 src/test/run-make/obtain-borrowck/output.stdout create mode 100644 src/test/run-make/obtain-borrowck/test.rs diff --git a/compiler/rustc_mir/src/borrow_check/consumers.rs b/compiler/rustc_mir/src/borrow_check/consumers.rs index 28c2c750136ca..77509d173bf44 100644 --- a/compiler/rustc_mir/src/borrow_check/consumers.rs +++ b/compiler/rustc_mir/src/borrow_check/consumers.rs @@ -15,6 +15,15 @@ pub use super::{ /// This function computes Polonius facts for the given body. It makes a copy of /// the body because it needs to regenerate the region identifiers. +/// +/// Note: +/// * This function will panic if the required body was already stolen. This +/// can, for example, happen when requesting a body of a `const` function +/// because they are evaluated during typechecking. The panic can be avoided +/// by overriding the `mir_borrowck` query. You can find a complete example +/// that shows how to do this at `src/test/run-make/obtain-borrowck/`. +/// * This function will also panic if computation of Polonius facts +/// (`-Zpolonius` flag) is not enabled. pub fn get_body_with_borrowck_facts<'tcx>( tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam, diff --git a/src/test/run-make/obtain-borrowck/Makefile b/src/test/run-make/obtain-borrowck/Makefile new file mode 100644 index 0000000000000..ede3a9c42e773 --- /dev/null +++ b/src/test/run-make/obtain-borrowck/Makefile @@ -0,0 +1,25 @@ +-include ../../run-make-fulldeps/tools.mk + +# This example shows how to implement a rustc driver that retrieves MIR bodies +# together with the borrow checker information. + +# How to run this +# $ ./x.py test src/test/run-make/obtain-borrowck + +DRIVER_BINARY := "$(TMPDIR)"/driver +BUILD_STAGE := $(RUST_BUILD_STAGE:$(TARGET)=) +RUSTC_SRC_LIB_DEPS := $(BUILD_DIR)/$(TARGET)/$(BUILD_STAGE)rustc/release/deps/ +RUSTC_SRC_LIB := $(BUILD_DIR)/$(TARGET)/$(BUILD_STAGE)rustc/$(TARGET)/release/deps/ +SYSROOT := $(shell $(RUSTC) --print sysroot) +DRIVER_RPATH_ENV = \ + $(LD_LIB_PATH_ENVVAR)="${RUSTC_SRC_LIB}:$(HOST_RPATH_DIR)/rustlib/$(TARGET)/lib/:$($(LD_LIB_PATH_ENVVAR))" + +all: + $(RUSTC) -L $(RUSTC_SRC_LIB) -L $(RUSTC_SRC_LIB_DEPS) driver.rs -o "$(DRIVER_BINARY)" + $(DRIVER_RPATH_ENV) "$(DRIVER_BINARY)" --sysroot $(SYSROOT) test.rs -o "$(TMPDIR)/driver_test" > "$(TMPDIR)"/output.stdout + +ifdef RUSTC_BLESS_TEST + cp "$(TMPDIR)"/output.stdout output.stdout +else + $(DIFF) output.stdout "$(TMPDIR)"/output.stdout +endif diff --git a/src/test/run-make/obtain-borrowck/driver.rs b/src/test/run-make/obtain-borrowck/driver.rs new file mode 100644 index 0000000000000..308df0b030c27 --- /dev/null +++ b/src/test/run-make/obtain-borrowck/driver.rs @@ -0,0 +1,171 @@ +#![feature(rustc_private)] + +//! This program implements a rustc driver that retrieves MIR bodies with +//! borrowck information. This cannot be done in a straightforward way because +//! `get_body_with_borrowck_facts`–the function for retrieving a MIR body with +//! borrowck facts–can panic if the body is stolen before it is invoked. +//! Therefore, the driver overrides `mir_borrowck` query (this is done in the +//! `config` callback), which retrieves the body that is about to be borrow +//! checked and stores it in a thread local `MIR_BODIES`. Then, `after_analysis` +//! callback triggers borrow checking of all MIR bodies by retrieving +//! `optimized_mir` and pulls out the MIR bodies with the borrowck information +//! from the thread local storage. + +extern crate rustc_driver; +extern crate rustc_hir; +extern crate rustc_interface; +extern crate rustc_middle; +extern crate rustc_mir; +extern crate rustc_session; + +use rustc_driver::Compilation; +use rustc_hir::def_id::LocalDefId; +use rustc_hir::itemlikevisit::ItemLikeVisitor; +use rustc_interface::interface::Compiler; +use rustc_interface::{Config, Queries}; +use rustc_middle::ty::query::query_values::mir_borrowck; +use rustc_middle::ty::query::Providers; +use rustc_middle::ty::{self, TyCtxt}; +use rustc_mir::consumers::BodyWithBorrowckFacts; +use rustc_session::Session; +use std::cell::RefCell; +use std::collections::HashMap; +use std::thread_local; + +fn main() { + let exit_code = rustc_driver::catch_with_exit_code(move || { + let mut rustc_args: Vec<_> = std::env::args().collect(); + // We must pass -Zpolonius so that the borrowck information is computed. + rustc_args.push("-Zpolonius".to_owned()); + let mut callbacks = CompilerCalls::default(); + // Call the Rust compiler with our callbacks. + rustc_driver::RunCompiler::new(&rustc_args, &mut callbacks).run() + }); + std::process::exit(exit_code); +} + +#[derive(Default)] +pub struct CompilerCalls; + +impl rustc_driver::Callbacks for CompilerCalls { + + // In this callback we override the mir_borrowck query. + fn config(&mut self, config: &mut Config) { + assert!(config.override_queries.is_none()); + config.override_queries = Some(override_queries); + } + + // In this callback we trigger borrow checking of all functions and obtain + // the result. + fn after_analysis<'tcx>( + &mut self, + compiler: &Compiler, + queries: &'tcx Queries<'tcx>, + ) -> Compilation { + compiler.session().abort_if_errors(); + queries.global_ctxt().unwrap().peek_mut().enter(|tcx| { + + // Collect definition ids of MIR bodies. + let hir = tcx.hir(); + let krate = hir.krate(); + let mut visitor = HirVisitor { bodies: Vec::new() }; + krate.visit_all_item_likes(&mut visitor); + + // Trigger borrow checking of all bodies. + for def_id in visitor.bodies { + let _ = tcx.optimized_mir(def_id); + } + + // See what bodies were borrow checked. + let mut bodies = get_bodies(tcx); + bodies.sort_by(|(def_id1, _), (def_id2, _)| def_id1.cmp(def_id2)); + println!("Bodies retrieved for:"); + for (def_id, body) in bodies { + println!("{}", def_id); + assert!(body.input_facts.cfg_edge.len() > 0); + } + }); + + Compilation::Continue + } +} + +fn override_queries(_session: &Session, local: &mut Providers, external: &mut Providers) { + local.mir_borrowck = mir_borrowck; + external.mir_borrowck = mir_borrowck; +} + +// Since mir_borrowck does not have access to any other state, we need to use a +// thread-local for storing the obtained MIR bodies. +// +// Note: We are using 'static lifetime here, which is in general unsound. +// Unfortunately, that is the only lifetime allowed here. Our use is safe +// because we cast it back to `'tcx` before using. +thread_local! { + pub static MIR_BODIES: + RefCell>> = + RefCell::new(HashMap::new()); +} + +fn mir_borrowck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> mir_borrowck<'tcx> { + let body_with_facts = rustc_mir::consumers::get_body_with_borrowck_facts( + tcx, + ty::WithOptConstParam::unknown(def_id), + ); + // SAFETY: The reader casts the 'static lifetime to 'tcx before using it. + let body_with_facts: BodyWithBorrowckFacts<'static> = + unsafe { std::mem::transmute(body_with_facts) }; + MIR_BODIES.with(|state| { + let mut map = state.borrow_mut(); + assert!(map.insert(def_id, body_with_facts).is_none()); + }); + let mut providers = Providers::default(); + rustc_mir::provide(&mut providers); + let original_mir_borrowck = providers.mir_borrowck; + original_mir_borrowck(tcx, def_id) +} + +/// Visitor that collects all body definition ids mentioned in the program. +struct HirVisitor { + bodies: Vec, +} + +impl<'tcx> ItemLikeVisitor<'tcx> for HirVisitor { + fn visit_item(&mut self, item: &rustc_hir::Item) { + if let rustc_hir::ItemKind::Fn(..) = item.kind { + self.bodies.push(item.def_id); + } + } + + fn visit_trait_item(&mut self, trait_item: &rustc_hir::TraitItem) { + if let rustc_hir::TraitItemKind::Fn(_, trait_fn) = &trait_item.kind { + if let rustc_hir::TraitFn::Provided(_) = trait_fn { + self.bodies.push(trait_item.def_id); + } + } + } + + fn visit_impl_item(&mut self, impl_item: &rustc_hir::ImplItem) { + if let rustc_hir::ImplItemKind::Fn(..) = impl_item.kind { + self.bodies.push(impl_item.def_id); + } + } + + fn visit_foreign_item(&mut self, _foreign_item: &rustc_hir::ForeignItem) {} +} + +/// Pull MIR bodies stored in the thread-local. +fn get_bodies<'tcx>(tcx: TyCtxt<'tcx>) -> Vec<(String, BodyWithBorrowckFacts<'tcx>)> { + MIR_BODIES.with(|state| { + let mut map = state.borrow_mut(); + map.drain() + .map(|(def_id, body)| { + let def_path = tcx.def_path(def_id.to_def_id()); + // SAFETY: For soundness we need to ensure that the bodies have + // the same lifetime (`'tcx`), which they had before they were + // stored in the thread local. + (def_path.to_string_no_crate_verbose(), body) + }) + .collect() + }) +} diff --git a/src/test/run-make/obtain-borrowck/output.stdout b/src/test/run-make/obtain-borrowck/output.stdout new file mode 100644 index 0000000000000..e011622e6b2a3 --- /dev/null +++ b/src/test/run-make/obtain-borrowck/output.stdout @@ -0,0 +1,8 @@ +Bodies retrieved for: +::X::provided +::foo +::main +::main::{constant#0} +::{impl#0}::new +::{impl#1}::provided +::{impl#1}::required diff --git a/src/test/run-make/obtain-borrowck/test.rs b/src/test/run-make/obtain-borrowck/test.rs new file mode 100644 index 0000000000000..f7b4b41feaf97 --- /dev/null +++ b/src/test/run-make/obtain-borrowck/test.rs @@ -0,0 +1,32 @@ +trait X { + fn provided(&self) -> usize { + 5 + } + fn required(&self) -> u32; +} + +struct Bar; + +impl Bar { + fn new() -> Self { + Self + } +} + +impl X for Bar { + fn provided(&self) -> usize { + 1 + } + fn required(&self) -> u32 { + 7 + } +} + +const fn foo() -> usize { + 1 +} + +fn main() { + let bar: [Bar; foo()] = [Bar::new()]; + assert_eq!(bar[0].provided(), foo()); +} From d882b5132637c32396f42d09038d4e9dd3b68787 Mon Sep 17 00:00:00 2001 From: Vytautas Astrauskas Date: Fri, 23 Jul 2021 12:43:54 +0200 Subject: [PATCH 3/7] Move obtain-borrowck to run-make-fulldeps. --- .../obtain-borrowck/Makefile | 20 +++++++++++++++ .../obtain-borrowck/driver.rs | 0 .../obtain-borrowck/output.stdout | 0 .../obtain-borrowck/test.rs | 0 src/test/run-make/obtain-borrowck/Makefile | 25 ------------------- 5 files changed, 20 insertions(+), 25 deletions(-) create mode 100644 src/test/run-make-fulldeps/obtain-borrowck/Makefile rename src/test/{run-make => run-make-fulldeps}/obtain-borrowck/driver.rs (100%) rename src/test/{run-make => run-make-fulldeps}/obtain-borrowck/output.stdout (100%) rename src/test/{run-make => run-make-fulldeps}/obtain-borrowck/test.rs (100%) delete mode 100644 src/test/run-make/obtain-borrowck/Makefile diff --git a/src/test/run-make-fulldeps/obtain-borrowck/Makefile b/src/test/run-make-fulldeps/obtain-borrowck/Makefile new file mode 100644 index 0000000000000..35314f2738bc3 --- /dev/null +++ b/src/test/run-make-fulldeps/obtain-borrowck/Makefile @@ -0,0 +1,20 @@ +include ../tools.mk + +# This example shows how to implement a rustc driver that retrieves MIR bodies +# together with the borrow checker information. + +# How to run this +# $ ./x.py test src/test/run-make/obtain-borrowck + +DRIVER_BINARY := "$(TMPDIR)"/driver +SYSROOT := $(shell $(RUSTC) --print sysroot) + +all: + $(RUSTC) driver.rs -o "$(DRIVER_BINARY)" + $(TARGET_RPATH_ENV) "$(DRIVER_BINARY)" --sysroot $(SYSROOT) test.rs -o "$(TMPDIR)/driver_test" > "$(TMPDIR)"/output.stdout + +ifdef RUSTC_BLESS_TEST + cp "$(TMPDIR)"/output.stdout output.stdout +else + $(DIFF) output.stdout "$(TMPDIR)"/output.stdout +endif diff --git a/src/test/run-make/obtain-borrowck/driver.rs b/src/test/run-make-fulldeps/obtain-borrowck/driver.rs similarity index 100% rename from src/test/run-make/obtain-borrowck/driver.rs rename to src/test/run-make-fulldeps/obtain-borrowck/driver.rs diff --git a/src/test/run-make/obtain-borrowck/output.stdout b/src/test/run-make-fulldeps/obtain-borrowck/output.stdout similarity index 100% rename from src/test/run-make/obtain-borrowck/output.stdout rename to src/test/run-make-fulldeps/obtain-borrowck/output.stdout diff --git a/src/test/run-make/obtain-borrowck/test.rs b/src/test/run-make-fulldeps/obtain-borrowck/test.rs similarity index 100% rename from src/test/run-make/obtain-borrowck/test.rs rename to src/test/run-make-fulldeps/obtain-borrowck/test.rs diff --git a/src/test/run-make/obtain-borrowck/Makefile b/src/test/run-make/obtain-borrowck/Makefile deleted file mode 100644 index ede3a9c42e773..0000000000000 --- a/src/test/run-make/obtain-borrowck/Makefile +++ /dev/null @@ -1,25 +0,0 @@ --include ../../run-make-fulldeps/tools.mk - -# This example shows how to implement a rustc driver that retrieves MIR bodies -# together with the borrow checker information. - -# How to run this -# $ ./x.py test src/test/run-make/obtain-borrowck - -DRIVER_BINARY := "$(TMPDIR)"/driver -BUILD_STAGE := $(RUST_BUILD_STAGE:$(TARGET)=) -RUSTC_SRC_LIB_DEPS := $(BUILD_DIR)/$(TARGET)/$(BUILD_STAGE)rustc/release/deps/ -RUSTC_SRC_LIB := $(BUILD_DIR)/$(TARGET)/$(BUILD_STAGE)rustc/$(TARGET)/release/deps/ -SYSROOT := $(shell $(RUSTC) --print sysroot) -DRIVER_RPATH_ENV = \ - $(LD_LIB_PATH_ENVVAR)="${RUSTC_SRC_LIB}:$(HOST_RPATH_DIR)/rustlib/$(TARGET)/lib/:$($(LD_LIB_PATH_ENVVAR))" - -all: - $(RUSTC) -L $(RUSTC_SRC_LIB) -L $(RUSTC_SRC_LIB_DEPS) driver.rs -o "$(DRIVER_BINARY)" - $(DRIVER_RPATH_ENV) "$(DRIVER_BINARY)" --sysroot $(SYSROOT) test.rs -o "$(TMPDIR)/driver_test" > "$(TMPDIR)"/output.stdout - -ifdef RUSTC_BLESS_TEST - cp "$(TMPDIR)"/output.stdout output.stdout -else - $(DIFF) output.stdout "$(TMPDIR)"/output.stdout -endif From f13396ed11b921d42f4a534797f7d33e505e608a Mon Sep 17 00:00:00 2001 From: Vytautas Astrauskas Date: Fri, 23 Jul 2021 13:26:41 +0200 Subject: [PATCH 4/7] Fix typo in a comment. --- src/test/run-make-fulldeps/obtain-borrowck/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/run-make-fulldeps/obtain-borrowck/Makefile b/src/test/run-make-fulldeps/obtain-borrowck/Makefile index 35314f2738bc3..c395ed5981774 100644 --- a/src/test/run-make-fulldeps/obtain-borrowck/Makefile +++ b/src/test/run-make-fulldeps/obtain-borrowck/Makefile @@ -4,7 +4,7 @@ include ../tools.mk # together with the borrow checker information. # How to run this -# $ ./x.py test src/test/run-make/obtain-borrowck +# $ ./x.py test src/test/run-make-fulldeps/obtain-borrowck DRIVER_BINARY := "$(TMPDIR)"/driver SYSROOT := $(shell $(RUSTC) --print sysroot) From e5e6acdd006bd1479951e192e189f491cef5f11b Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 30 Jul 2021 15:13:28 +0300 Subject: [PATCH 5/7] Update compiler/rustc_mir/src/borrow_check/consumers.rs --- compiler/rustc_mir/src/borrow_check/consumers.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compiler/rustc_mir/src/borrow_check/consumers.rs b/compiler/rustc_mir/src/borrow_check/consumers.rs index 77509d173bf44..f6e4e3888418f 100644 --- a/compiler/rustc_mir/src/borrow_check/consumers.rs +++ b/compiler/rustc_mir/src/borrow_check/consumers.rs @@ -24,6 +24,8 @@ pub use super::{ /// that shows how to do this at `src/test/run-make/obtain-borrowck/`. /// * This function will also panic if computation of Polonius facts /// (`-Zpolonius` flag) is not enabled. +/// +/// * Polonius is highly unstable, so expect regular changes in its signature or other details. pub fn get_body_with_borrowck_facts<'tcx>( tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam, From 25a7c3b73340d7339c6921b1bbabd09b07c2947a Mon Sep 17 00:00:00 2001 From: Vytautas Astrauskas Date: Sat, 31 Jul 2021 18:02:28 +0200 Subject: [PATCH 6/7] Fix obtain-borrowck failure on MSVC. --- src/test/run-make-fulldeps/obtain-borrowck/Makefile | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/test/run-make-fulldeps/obtain-borrowck/Makefile b/src/test/run-make-fulldeps/obtain-borrowck/Makefile index c395ed5981774..39832c4c79bb5 100644 --- a/src/test/run-make-fulldeps/obtain-borrowck/Makefile +++ b/src/test/run-make-fulldeps/obtain-borrowck/Makefile @@ -9,9 +9,15 @@ include ../tools.mk DRIVER_BINARY := "$(TMPDIR)"/driver SYSROOT := $(shell $(RUSTC) --print sysroot) +ifdef IS_MSVC +LIBSTD := -L "$(SYSROOT)\\lib\\rustlib\\$(TARGET)\\lib" +else +LIBSTD := +endif + all: $(RUSTC) driver.rs -o "$(DRIVER_BINARY)" - $(TARGET_RPATH_ENV) "$(DRIVER_BINARY)" --sysroot $(SYSROOT) test.rs -o "$(TMPDIR)/driver_test" > "$(TMPDIR)"/output.stdout + $(TARGET_RPATH_ENV) "$(DRIVER_BINARY)" --sysroot $(SYSROOT) $(LIBSTD) test.rs -o "$(TMPDIR)/driver_test" > "$(TMPDIR)"/output.stdout ifdef RUSTC_BLESS_TEST cp "$(TMPDIR)"/output.stdout output.stdout From 9142d6ddf0634066ce4905793aca22948f0d2225 Mon Sep 17 00:00:00 2001 From: Vytautas Astrauskas Date: Tue, 17 Aug 2021 13:06:27 +0200 Subject: [PATCH 7/7] Fix obtain-borrowck failure on Windows. --- src/test/run-make-fulldeps/obtain-borrowck/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/run-make-fulldeps/obtain-borrowck/Makefile b/src/test/run-make-fulldeps/obtain-borrowck/Makefile index 39832c4c79bb5..223993125c809 100644 --- a/src/test/run-make-fulldeps/obtain-borrowck/Makefile +++ b/src/test/run-make-fulldeps/obtain-borrowck/Makefile @@ -9,7 +9,7 @@ include ../tools.mk DRIVER_BINARY := "$(TMPDIR)"/driver SYSROOT := $(shell $(RUSTC) --print sysroot) -ifdef IS_MSVC +ifdef IS_WINDOWS LIBSTD := -L "$(SYSROOT)\\lib\\rustlib\\$(TARGET)\\lib" else LIBSTD :=