diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index bd1d49fb24dc3..8fbbd7c4a2e49 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -150,13 +150,13 @@ All pull requests are reviewed by another person. We have a bot, request. If you want to request that a specific person reviews your pull request, -you can add an `r?` to the message. For example, [Steve][steveklabnik] usually reviews +you can add an `r?` to the pull request description. For example, [Steve][steveklabnik] usually reviews documentation changes. So if you were to make a documentation change, add r? @steveklabnik -to the end of the message, and @rust-highfive will assign [@steveklabnik][steveklabnik] instead -of a random person. This is entirely optional. +to the end of the pull request description, and [@rust-highfive][rust-highfive] will assign +[@steveklabnik][steveklabnik] instead of a random person. This is entirely optional. After someone has reviewed your pull request, they will leave an annotation on the pull request with an `r+`. It will look something like this: diff --git a/src/libcore/any.rs b/src/libcore/any.rs index 57a2aecd8be6d..466750fc7d2c6 100644 --- a/src/libcore/any.rs +++ b/src/libcore/any.rs @@ -68,7 +68,7 @@ use crate::intrinsics; // Any trait /////////////////////////////////////////////////////////////////////////////// -/// A type to emulate dynamic typing. +/// A trait to emulate dynamic typing. /// /// Most types implement `Any`. However, any type which contains a non-`'static` reference does not. /// See the [module-level documentation][mod] for more details. diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index 38b3fab6d7535..913c0f96d118d 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -26,7 +26,7 @@ pub const DIGITS: u32 = 6; /// [Machine epsilon] value for `f32`. /// -/// This is the difference between `1.0` and the next largest representable number. +/// This is the difference between `1.0` and the next larger representable number. /// /// [Machine epsilon]: https://en.wikipedia.org/wiki/Machine_epsilon #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index f093bae9590ea..6ca830b1f38af 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -26,7 +26,7 @@ pub const DIGITS: u32 = 15; /// [Machine epsilon] value for `f64`. /// -/// This is the difference between `1.0` and the next largest representable number. +/// This is the difference between `1.0` and the next larger representable number. /// /// [Machine epsilon]: https://en.wikipedia.org/wiki/Machine_epsilon #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/panic.rs b/src/libcore/panic.rs index cdd38449a1be2..99b372d92c8b6 100644 --- a/src/libcore/panic.rs +++ b/src/libcore/panic.rs @@ -266,6 +266,16 @@ impl fmt::Display for Location<'_> { #[unstable(feature = "std_internals", issue = "0")] #[doc(hidden)] pub unsafe trait BoxMeUp { - fn box_me_up(&mut self) -> *mut (dyn Any + Send); + /// Take full ownership of the contents. + /// The return type is actually `Box`, but we cannot use `Box` in libcore. + /// + /// After this method got called, only some dummy default value is left in `self`. + /// Calling this method twice, or calling `get` after calling this method, is an error. + /// + /// The argument is borrowed because the panic runtime (`__rust_start_panic`) only + /// gets a borrowed `dyn BoxMeUp`. + fn take_box(&mut self) -> *mut (dyn Any + Send); + + /// Just borrow the contents. fn get(&mut self) -> &(dyn Any + Send); } diff --git a/src/libcore/panicking.rs b/src/libcore/panicking.rs index 4833194be37ac..5a8d647396dda 100644 --- a/src/libcore/panicking.rs +++ b/src/libcore/panicking.rs @@ -11,13 +11,13 @@ //! ``` //! //! This definition allows for panicking with any general message, but it does not -//! allow for failing with a `Box` value. The reason for this is that libcore -//! is not allowed to allocate. +//! allow for failing with a `Box` value. (`PanicInfo` just contains a `&(dyn Any + Send)`, +//! for which we fill in a dummy value in `PanicInfo::internal_constructor`.) +//! The reason for this is that libcore is not allowed to allocate. //! //! This module contains a few other panicking functions, but these are just the //! necessary lang items for the compiler. All panics are funneled through this -//! one function. Currently, the actual symbol is declared in the standard -//! library, but the location of this may change over time. +//! one function. The actual symbol is declared through the `#[panic_handler]` attribute. // ignore-tidy-undocumented-unsafe @@ -72,6 +72,7 @@ pub fn panic_fmt(fmt: fmt::Arguments<'_>, location: &Location<'_>) -> ! { } // NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call + // that gets resolved to the `#[panic_handler]` function. extern "Rust" { #[lang = "panic_impl"] fn panic_impl(pi: &PanicInfo<'_>) -> !; diff --git a/src/libcore/ptr/mod.rs b/src/libcore/ptr/mod.rs index 39d56958f5de0..1e051dbebcaf8 100644 --- a/src/libcore/ptr/mod.rs +++ b/src/libcore/ptr/mod.rs @@ -1074,17 +1074,22 @@ impl *const T { /// operation because the returned value could be pointing to invalid /// memory. /// - /// When calling this method, you have to ensure that if the pointer is - /// non-NULL, then it is properly aligned, dereferencable (for the whole - /// size of `T`) and points to an initialized instance of `T`. This applies - /// even if the result of this method is unused! + /// When calling this method, you have to ensure that *either* the pointer is NULL *or* + /// all of the following is true: + /// - it is properly aligned + /// - it must point to an initialized instance of T; in particular, the pointer must be + /// "dereferencable" in the sense defined [here]. + /// + /// This applies even if the result of this method is unused! /// (The part about being initialized is not yet fully decided, but until /// it is, the only safe approach is to ensure that they are indeed initialized.) /// /// Additionally, the lifetime `'a` returned is arbitrarily chosen and does - /// not necessarily reflect the actual lifetime of the data. It is up to the - /// caller to ensure that for the duration of this lifetime, the memory this - /// pointer points to does not get written to outside of `UnsafeCell`. + /// not necessarily reflect the actual lifetime of the data. *You* must enforce + /// Rust's aliasing rules. In particular, for the duration of this lifetime, + /// the memory the pointer points to must not get mutated (except inside `UnsafeCell`). + /// + /// [here]: crate::ptr#safety /// /// # Examples /// @@ -1929,18 +1934,23 @@ impl *mut T { /// of the returned pointer, nor can it ensure that the lifetime `'a` /// returned is indeed a valid lifetime for the contained data. /// - /// When calling this method, you have to ensure that if the pointer is - /// non-NULL, then it is properly aligned, dereferencable (for the whole - /// size of `T`) and points to an initialized instance of `T`. This applies - /// even if the result of this method is unused! + /// When calling this method, you have to ensure that *either* the pointer is NULL *or* + /// all of the following is true: + /// - it is properly aligned + /// - it must point to an initialized instance of T; in particular, the pointer must be + /// "dereferencable" in the sense defined [here]. + /// + /// This applies even if the result of this method is unused! /// (The part about being initialized is not yet fully decided, but until /// it is the only safe approach is to ensure that they are indeed initialized.) /// /// Additionally, the lifetime `'a` returned is arbitrarily chosen and does - /// not necessarily reflect the actual lifetime of the data. It is up to the - /// caller to ensure that for the duration of this lifetime, the memory this - /// pointer points to does not get accessed through any other pointer. + /// not necessarily reflect the actual lifetime of the data. *You* must enforce + /// Rust's aliasing rules. In particular, for the duration of this lifetime, + /// the memory this pointer points to must not get accessed (read or written) + /// through any other pointer. /// + /// [here]: crate::ptr#safety /// [`as_ref`]: #method.as_ref /// /// # Examples diff --git a/src/libpanic_unwind/lib.rs b/src/libpanic_unwind/lib.rs index d97a7a8a87d8d..0c834e5c2a05c 100644 --- a/src/libpanic_unwind/lib.rs +++ b/src/libpanic_unwind/lib.rs @@ -94,5 +94,5 @@ pub unsafe extern "C" fn __rust_maybe_catch_panic(f: fn(*mut u8), #[unwind(allowed)] pub unsafe extern "C" fn __rust_start_panic(payload: usize) -> u32 { let payload = payload as *mut &mut dyn BoxMeUp; - imp::panic(Box::from_raw((*payload).box_me_up())) + imp::panic(Box::from_raw((*payload).take_box())) } diff --git a/src/librustc/arena.rs b/src/librustc/arena.rs index 9b13a910c6174..193b04eabb3fb 100644 --- a/src/librustc/arena.rs +++ b/src/librustc/arena.rs @@ -93,6 +93,7 @@ macro_rules! arena_types { rustc::hir::def_id::CrateNum > >, + [few] hir_forest: rustc::hir::map::Forest, [few] diagnostic_items: rustc_data_structures::fx::FxHashMap< syntax::symbol::Symbol, rustc::hir::def_id::DefId, diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index fc754c5e675e6..5bf5a93ad0102 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -200,7 +200,7 @@ pub struct Map<'hir> { map: HirEntryMap<'hir>, - definitions: &'hir Definitions, + definitions: Definitions, /// The reverse mapping of `node_to_hir_id`. hir_to_node_id: FxHashMap, @@ -267,8 +267,8 @@ impl<'hir> Map<'hir> { } #[inline] - pub fn definitions(&self) -> &'hir Definitions { - self.definitions + pub fn definitions(&self) -> &Definitions { + &self.definitions } pub fn def_key(&self, def_id: DefId) -> DefKey { @@ -1251,7 +1251,7 @@ impl Named for ImplItem { fn name(&self) -> Name { self.ident.name } } pub fn map_crate<'hir>(sess: &crate::session::Session, cstore: &CrateStoreDyn, forest: &'hir Forest, - definitions: &'hir Definitions) + definitions: Definitions) -> Map<'hir> { let _prof_timer = sess.prof.generic_activity("build_hir_map"); @@ -1260,7 +1260,7 @@ pub fn map_crate<'hir>(sess: &crate::session::Session, .map(|(node_id, &hir_id)| (hir_id, node_id)).collect(); let (map, crate_hash) = { - let hcx = crate::ich::StableHashingContext::new(sess, &forest.krate, definitions, cstore); + let hcx = crate::ich::StableHashingContext::new(sess, &forest.krate, &definitions, cstore); let mut collector = NodeCollector::root(sess, &forest.krate, diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index b670658a10a50..5a940f2f80aa2 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -1545,8 +1545,20 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { infer::Types(ref exp_found) => self.expected_found_str_ty(exp_found), infer::Regions(ref exp_found) => self.expected_found_str(exp_found), infer::Consts(ref exp_found) => self.expected_found_str(exp_found), - infer::TraitRefs(ref exp_found) => self.expected_found_str(exp_found), - infer::PolyTraitRefs(ref exp_found) => self.expected_found_str(exp_found), + infer::TraitRefs(ref exp_found) => { + let pretty_exp_found = ty::error::ExpectedFound { + expected: exp_found.expected.print_only_trait_path(), + found: exp_found.found.print_only_trait_path() + }; + self.expected_found_str(&pretty_exp_found) + }, + infer::PolyTraitRefs(ref exp_found) => { + let pretty_exp_found = ty::error::ExpectedFound { + expected: exp_found.expected.print_only_trait_path(), + found: exp_found.found.print_only_trait_path() + }; + self.expected_found_str(&pretty_exp_found) + }, } } diff --git a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs index bfa8353ca343f..3b4d06aab27ef 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -401,7 +401,7 @@ impl NiceRegionError<'me, 'tcx> { format!( "{}`{}` would have to be implemented for the type `{}`", if leading_ellipsis { "..." } else { "" }, - expected_trait_ref, + expected_trait_ref.map(|tr| tr.print_only_trait_path()), expected_trait_ref.map(|tr| tr.self_ty()), ) } else { @@ -409,7 +409,7 @@ impl NiceRegionError<'me, 'tcx> { "{}`{}` must implement `{}`", if leading_ellipsis { "..." } else { "" }, expected_trait_ref.map(|tr| tr.self_ty()), - expected_trait_ref, + expected_trait_ref.map(|tr| tr.print_only_trait_path()), ) }; @@ -449,14 +449,14 @@ impl NiceRegionError<'me, 'tcx> { let mut note = if passive_voice { format!( "...but `{}` is actually implemented for the type `{}`", - actual_trait_ref, + actual_trait_ref.map(|tr| tr.print_only_trait_path()), actual_trait_ref.map(|tr| tr.self_ty()), ) } else { format!( "...but `{}` actually implements `{}`", actual_trait_ref.map(|tr| tr.self_ty()), - actual_trait_ref, + actual_trait_ref.map(|tr| tr.print_only_trait_path()), ) }; diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 5e204d83aef20..b3ddffc8b12f1 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -1292,7 +1292,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } pub fn trait_ref_to_string(&self, t: &ty::TraitRef<'tcx>) -> String { - self.resolve_vars_if_possible(t).to_string() + self.resolve_vars_if_possible(t).print_only_trait_path().to_string() } /// If `TyVar(vid)` resolves to a type, return that type. Else, return the diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 2f865f1f8b501..05543f1d2ef73 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -800,8 +800,13 @@ impl<'a, 'tcx> LateContext<'a, 'tcx> { // This shouldn't ever be needed, but just in case: path.push(match trait_ref { Some(trait_ref) => { - Symbol::intern(&format!("", trait_ref, - self_ty)) + Symbol::intern( + &format!( + "", + trait_ref.print_only_trait_path(), + self_ty + ) + ) }, None => Symbol::intern(&format!("", self_ty)), }); diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index c745dd9444cd6..3e3184260f099 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -104,10 +104,6 @@ pub struct Body<'tcx> { /// and used for debuginfo. Indexed by a `SourceScope`. pub source_scopes: IndexVec, - /// Crate-local information for each source scope, that can't (and - /// needn't) be tracked across crates. - pub source_scope_local_data: ClearCrossCrate>, - /// The yield type of the function, if it is a generator. pub yield_ty: Option>, @@ -163,7 +159,6 @@ impl<'tcx> Body<'tcx> { pub fn new( basic_blocks: IndexVec>, source_scopes: IndexVec, - source_scope_local_data: ClearCrossCrate>, local_decls: LocalDecls<'tcx>, user_type_annotations: CanonicalUserTypeAnnotations<'tcx>, arg_count: usize, @@ -183,7 +178,6 @@ impl<'tcx> Body<'tcx> { phase: MirPhase::Build, basic_blocks, source_scopes, - source_scope_local_data, yield_ty: None, generator_drop: None, generator_layout: None, @@ -429,6 +423,13 @@ pub enum ClearCrossCrate { } impl ClearCrossCrate { + pub fn as_ref(&'a self) -> ClearCrossCrate<&'a T> { + match self { + ClearCrossCrate::Clear => ClearCrossCrate::Clear, + ClearCrossCrate::Set(v) => ClearCrossCrate::Set(v), + } + } + pub fn assert_crate_local(self) -> T { match self { ClearCrossCrate::Clear => bug!("unwrapping cross-crate data"), @@ -2021,6 +2022,10 @@ rustc_index::newtype_index! { pub struct SourceScopeData { pub span: Span, pub parent_scope: Option, + + /// Crate-local information for this source scope, that can't (and + /// needn't) be tracked across crates. + pub local_data: ClearCrossCrate, } #[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)] diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index 464d4c74366e5..348d516d99f60 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -317,6 +317,7 @@ macro_rules! make_mir_visitor { let SourceScopeData { span, parent_scope, + local_data: _, } = scope_data; self.visit_span(span); diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 6e723cdc999b0..90db1fe319556 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -737,7 +737,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let is_try = self.tcx.sess.source_map().span_to_snippet(span) .map(|s| &s == "?") .unwrap_or(false); - let is_from = format!("{}", trait_ref).starts_with("std::convert::From<"); + let is_from = + format!("{}", trait_ref.print_only_trait_path()) + .starts_with("std::convert::From<"); let (message, note) = if is_try && is_from { (Some(format!( "`?` couldn't convert the error to `{}`", @@ -768,7 +770,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { format!( "{}the trait `{}` is not implemented for `{}`", pre_message, - trait_ref, + trait_ref.print_only_trait_path(), trait_ref.self_ty(), ) }; @@ -1189,7 +1191,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { if param_ty => { // Missing generic type parameter bound. let param_name = self_ty.to_string(); - let constraint = trait_ref.to_string(); + let constraint = trait_ref.print_only_trait_path().to_string(); if suggest_constraining_type_param( generics, &mut err, @@ -1416,7 +1418,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let msg = format!( "the trait bound `{}: {}` is not satisfied", found, - obligation.parent_trait_ref.skip_binder(), + obligation.parent_trait_ref.skip_binder().print_only_trait_path(), ); if has_custom_message { err.note(&msg); @@ -1430,7 +1432,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } err.span_label(span, &format!( "expected an implementor of trait `{}`", - obligation.parent_trait_ref.skip_binder(), + obligation.parent_trait_ref.skip_binder().print_only_trait_path(), )); err.span_suggestion( span, @@ -1562,7 +1564,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } else { err.note(&format!( "`{}` is implemented for `{:?}`, but not for `{:?}`", - trait_ref, + trait_ref.print_only_trait_path(), trait_type, trait_ref.skip_binder().self_ty(), )); @@ -2226,7 +2228,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { err.span_note(span, &format!( "future does not implement `{}` as this value is used across an await", - trait_ref, + trait_ref.print_only_trait_path(), )); // Add a note for the item obligation that remains - normally a note pointing to the @@ -2409,7 +2411,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref); err.note( &format!("required because of the requirements on the impl of `{}` for `{}`", - parent_trait_ref, + parent_trait_ref.print_only_trait_path(), parent_trait_ref.skip_binder().self_ty())); let parent_predicate = parent_trait_ref.to_predicate(); self.note_obligation_cause_code(err, diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 283fa56d11f4f..5f324527a2725 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -1044,7 +1044,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let trait_ref = stack.obligation.predicate.skip_binder().trait_ref; let self_ty = trait_ref.self_ty(); let cause = IntercrateAmbiguityCause::DownstreamCrate { - trait_desc: trait_ref.to_string(), + trait_desc: trait_ref.print_only_trait_path().to_string(), self_desc: if self_ty.has_concrete_skeleton() { Some(self_ty.to_string()) } else { @@ -1386,7 +1386,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { if !candidate_set.ambiguous && no_candidates_apply { let trait_ref = stack.obligation.predicate.skip_binder().trait_ref; let self_ty = trait_ref.self_ty(); - let trait_desc = trait_ref.to_string(); + let trait_desc = trait_ref.print_only_trait_path().to_string(); let self_desc = if self_ty.has_concrete_skeleton() { Some(self_ty.to_string()) } else { diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index 475037f54ba38..88a2db3dc6223 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -417,7 +417,7 @@ fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Option w.push('>'); } - write!(w, " {} for {}", trait_ref, tcx.type_of(impl_def_id)).unwrap(); + write!(w, " {} for {}", trait_ref.print_only_trait_path(), tcx.type_of(impl_def_id)).unwrap(); // The predicates will contain default bounds like `T: Sized`. We need to // remove these bounds, and add `T: ?Sized` to any untouched type parameters. diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs index d945c756f6662..b8ddf6078bda6 100644 --- a/src/librustc/traits/specialize/specialization_graph.rs +++ b/src/librustc/traits/specialize/specialization_graph.rs @@ -146,7 +146,7 @@ impl<'tcx> Children { let self_ty = trait_ref.self_ty(); OverlapError { with_impl: possible_sibling, - trait_desc: trait_ref.to_string(), + trait_desc: trait_ref.print_only_trait_path().to_string(), // Only report the `Self` type if it has at least // some outer concrete shell; otherwise, it's // not adding much information. diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 5a7078cdb2612..0b6937975aae1 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -995,7 +995,7 @@ impl<'tcx> Deref for TyCtxt<'tcx> { } pub struct GlobalCtxt<'tcx> { - pub arena: WorkerLocal>, + pub arena: &'tcx WorkerLocal>, interners: CtxtInterners<'tcx>, @@ -1170,6 +1170,7 @@ impl<'tcx> TyCtxt<'tcx> { local_providers: ty::query::Providers<'tcx>, extern_providers: ty::query::Providers<'tcx>, arenas: &'tcx AllArenas, + arena: &'tcx WorkerLocal>, resolutions: ty::ResolverOutputs, hir: hir_map::Map<'tcx>, on_disk_query_result_cache: query::OnDiskCache<'tcx>, @@ -1225,7 +1226,7 @@ impl<'tcx> TyCtxt<'tcx> { sess: s, lint_store, cstore, - arena: WorkerLocal::new(|_| Arena::default()), + arena, interners, dep_graph, prof: s.prof.clone(), diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 2a311ea962424..c941b3e5e4be9 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -449,7 +449,7 @@ pub trait PrettyPrinter<'tcx>: p!(print(self_ty)); if let Some(trait_ref) = trait_ref { - p!(write(" as "), print(trait_ref)); + p!(write(" as "), print(trait_ref.print_only_trait_path())); } Ok(cx) }) @@ -468,7 +468,7 @@ pub trait PrettyPrinter<'tcx>: p!(write("impl ")); if let Some(trait_ref) = trait_ref { - p!(print(trait_ref), write(" for ")); + p!(print(trait_ref.print_only_trait_path()), write(" for ")); } p!(print(self_ty)); @@ -619,7 +619,7 @@ pub trait PrettyPrinter<'tcx>: p!( write("{}", if first { " " } else { "+" }), - print(trait_ref)); + print(trait_ref.print_only_trait_path())); first = false; } } @@ -1696,6 +1696,30 @@ impl fmt::Display for ty::RegionKind { } } +/// Wrapper type for `ty::TraitRef` which opts-in to pretty printing only +/// the trait path. That is, it will print `Trait` instead of +/// `>`. +#[derive(Copy, Clone, TypeFoldable, Lift)] +pub struct TraitRefPrintOnlyTraitPath<'tcx>(ty::TraitRef<'tcx>); + +impl fmt::Debug for TraitRefPrintOnlyTraitPath<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self, f) + } +} + +impl ty::TraitRef<'tcx> { + pub fn print_only_trait_path(self) -> TraitRefPrintOnlyTraitPath<'tcx> { + TraitRefPrintOnlyTraitPath(self) + } +} + +impl ty::Binder> { + pub fn print_only_trait_path(self) -> ty::Binder> { + self.map_bound(|tr| tr.print_only_trait_path()) + } +} + forward_display_to_print! { Ty<'tcx>, &'tcx ty::List>, @@ -1705,6 +1729,7 @@ forward_display_to_print! { // because `for<'tcx>` isn't possible yet. ty::Binder<&'tcx ty::List>>, ty::Binder>, + ty::Binder>, ty::Binder>, ty::Binder>, ty::Binder>, @@ -1739,7 +1764,7 @@ define_print_and_forward_display! { // Use a type that can't appear in defaults of type parameters. let dummy_self = cx.tcx().mk_ty_infer(ty::FreshTy(0)); let trait_ref = self.with_self_ty(cx.tcx(), dummy_self); - p!(print(trait_ref)) + p!(print(trait_ref.print_only_trait_path())) } ty::ExistentialProjection<'tcx> { @@ -1783,7 +1808,11 @@ define_print_and_forward_display! { } ty::TraitRef<'tcx> { - p!(print_def_path(self.def_id, self.substs)); + p!(write("<{} as {}>", self.self_ty(), self.print_only_trait_path())) + } + + TraitRefPrintOnlyTraitPath<'tcx> { + p!(print_def_path(self.0.def_id, self.0.substs)); } ty::ParamTy { @@ -1799,7 +1828,8 @@ define_print_and_forward_display! { } ty::TraitPredicate<'tcx> { - p!(print(self.trait_ref.self_ty()), write(": "), print(self.trait_ref)) + p!(print(self.trait_ref.self_ty()), write(": "), + print(self.trait_ref.print_only_trait_path())) } ty::ProjectionPredicate<'tcx> { diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index a0e66d340ae9d..ffbf8813d309d 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -223,10 +223,7 @@ impl fmt::Debug for ty::FloatVarValue { impl fmt::Debug for ty::TraitRef<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - // FIXME(#59188) this is used across the compiler to print - // a `TraitRef` qualified (with the Self type explicit), - // instead of having a different way to make that choice. - write!(f, "<{} as {}>", self.self_ty(), self) + fmt::Display::fmt(self, f) } } diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 0c9fbfe664189..0b11a9efd81d7 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -682,6 +682,23 @@ impl<'tcx> TyCtxt<'tcx> { self.static_mutability(def_id) == Some(hir::Mutability::Mutable) } + /// Get the type of the pointer to the static that we use in MIR. + pub fn static_ptr_ty(&self, def_id: DefId) -> Ty<'tcx> { + // Make sure that any constants in the static's type are evaluated. + let static_ty = self.normalize_erasing_regions( + ty::ParamEnv::empty(), + self.type_of(def_id), + ); + + if self.is_mutable_static(def_id) { + self.mk_mut_ptr(static_ty) + } else if self.is_foreign_item(def_id) { + self.mk_imm_ptr(static_ty) + } else { + self.mk_imm_ref(self.lifetimes.re_erased, static_ty) + } + } + /// Expands the given impl trait type, stopping if the type is recursive. pub fn try_expand_impl_trait_type( self, diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 13829b842fd5f..c945de8f1e1dc 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -283,120 +283,127 @@ pub fn run_compiler( return sess.compile_status(); } - compiler.parse()?; - - if let Some(ppm) = &sess.opts.pretty { - if ppm.needs_ast_map() { - compiler.global_ctxt()?.peek_mut().enter(|tcx| { - let expanded_crate = compiler.expansion()?.take().0; - pretty::print_after_hir_lowering( - tcx, - compiler.input(), - &expanded_crate, + let linker = compiler.enter(|queries| { + let early_exit = || sess.compile_status().map(|_| None); + queries.parse()?; + + if let Some(ppm) = &sess.opts.pretty { + if ppm.needs_ast_map() { + queries.global_ctxt()?.peek_mut().enter(|tcx| { + let expanded_crate = queries.expansion()?.take().0; + pretty::print_after_hir_lowering( + tcx, + compiler.input(), + &expanded_crate, + *ppm, + compiler.output_file().as_ref().map(|p| &**p), + ); + Ok(()) + })?; + } else { + let krate = queries.parse()?.take(); + pretty::print_after_parsing( + sess, + &compiler.input(), + &krate, *ppm, compiler.output_file().as_ref().map(|p| &**p), ); - Ok(()) - })?; - } else { - let krate = compiler.parse()?.take(); - pretty::print_after_parsing( - sess, - &compiler.input(), - &krate, - *ppm, - compiler.output_file().as_ref().map(|p| &**p), - ); + } + return early_exit(); } - return sess.compile_status(); - } - if callbacks.after_parsing(compiler) == Compilation::Stop { - return sess.compile_status(); - } + if callbacks.after_parsing(compiler) == Compilation::Stop { + return early_exit(); + } - if sess.opts.debugging_opts.parse_only || - sess.opts.debugging_opts.show_span.is_some() || - sess.opts.debugging_opts.ast_json_noexpand { - return sess.compile_status(); - } + if sess.opts.debugging_opts.parse_only || + sess.opts.debugging_opts.show_span.is_some() || + sess.opts.debugging_opts.ast_json_noexpand { + return early_exit(); + } - { - let (_, lint_store) = &*compiler.register_plugins()?.peek(); + { + let (_, lint_store) = &*queries.register_plugins()?.peek(); - // Lint plugins are registered; now we can process command line flags. - if sess.opts.describe_lints { - describe_lints(&sess, &lint_store, true); - return sess.compile_status(); + // Lint plugins are registered; now we can process command line flags. + if sess.opts.describe_lints { + describe_lints(&sess, &lint_store, true); + return early_exit(); + } } - } - compiler.expansion()?; - if callbacks.after_expansion(compiler) == Compilation::Stop { - return sess.compile_status(); - } + queries.expansion()?; + if callbacks.after_expansion(compiler) == Compilation::Stop { + return early_exit(); + } - compiler.prepare_outputs()?; + queries.prepare_outputs()?; - if sess.opts.output_types.contains_key(&OutputType::DepInfo) - && sess.opts.output_types.len() == 1 - { - return sess.compile_status(); - } + if sess.opts.output_types.contains_key(&OutputType::DepInfo) + && sess.opts.output_types.len() == 1 + { + return early_exit(); + } - compiler.global_ctxt()?; + queries.global_ctxt()?; - if sess.opts.debugging_opts.no_analysis || - sess.opts.debugging_opts.ast_json { - return sess.compile_status(); - } + if sess.opts.debugging_opts.no_analysis || + sess.opts.debugging_opts.ast_json { + return early_exit(); + } - if sess.opts.debugging_opts.save_analysis { - let expanded_crate = &compiler.expansion()?.peek().0; - let crate_name = compiler.crate_name()?.peek().clone(); - compiler.global_ctxt()?.peek_mut().enter(|tcx| { - let result = tcx.analysis(LOCAL_CRATE); - - time(sess, "save analysis", || { - save::process_crate( - tcx, - &expanded_crate, - &crate_name, - &compiler.input(), - None, - DumpHandler::new(compiler.output_dir().as_ref().map(|p| &**p), &crate_name) - ) - }); - - result - // AST will be dropped *after* the `after_analysis` callback - // (needed by the RLS) - })?; - } else { - // Drop AST after creating GlobalCtxt to free memory - mem::drop(compiler.expansion()?.take()); - } + if sess.opts.debugging_opts.save_analysis { + let expanded_crate = &queries.expansion()?.peek().0; + let crate_name = queries.crate_name()?.peek().clone(); + queries.global_ctxt()?.peek_mut().enter(|tcx| { + let result = tcx.analysis(LOCAL_CRATE); + + time(sess, "save analysis", || { + save::process_crate( + tcx, + &expanded_crate, + &crate_name, + &compiler.input(), + None, + DumpHandler::new( + compiler.output_dir().as_ref().map(|p| &**p), &crate_name + ) + ) + }); - compiler.global_ctxt()?.peek_mut().enter(|tcx| tcx.analysis(LOCAL_CRATE))?; + result + // AST will be dropped *after* the `after_analysis` callback + // (needed by the RLS) + })?; + } else { + // Drop AST after creating GlobalCtxt to free memory + mem::drop(queries.expansion()?.take()); + } - if callbacks.after_analysis(compiler) == Compilation::Stop { - return sess.compile_status(); - } + queries.global_ctxt()?.peek_mut().enter(|tcx| tcx.analysis(LOCAL_CRATE))?; - if sess.opts.debugging_opts.save_analysis { - mem::drop(compiler.expansion()?.take()); - } + if callbacks.after_analysis(compiler) == Compilation::Stop { + return early_exit(); + } - compiler.ongoing_codegen()?; + if sess.opts.debugging_opts.save_analysis { + mem::drop(queries.expansion()?.take()); + } - // Drop GlobalCtxt after starting codegen to free memory - mem::drop(compiler.global_ctxt()?.take()); + queries.ongoing_codegen()?; - if sess.opts.debugging_opts.print_type_sizes { - sess.code_stats.print_type_sizes(); - } + if sess.opts.debugging_opts.print_type_sizes { + sess.code_stats.print_type_sizes(); + } - compiler.link()?; + let linker = queries.linker()?; + Ok(Some(linker)) + })?; + + if let Some(linker) = linker { + linker.link()? + } if sess.opts.debugging_opts.perf_stats { sess.print_perf_stats(); diff --git a/src/librustc_error_codes/error_codes/E0080.md b/src/librustc_error_codes/error_codes/E0080.md index 262bf00d38540..273238a943b4f 100644 --- a/src/librustc_error_codes/error_codes/E0080.md +++ b/src/librustc_error_codes/error_codes/E0080.md @@ -1,14 +1,18 @@ -This error indicates that the compiler was unable to sensibly evaluate a -constant expression that had to be evaluated. Attempting to divide by 0 -or causing integer overflow are two ways to induce this error. For example: +A constant value failed to get evaluated. + +Erroneous code example: ```compile_fail,E0080 enum Enum { X = (1 << 500), - Y = (1 / 0) + Y = (1 / 0), } ``` +This error indicates that the compiler was unable to sensibly evaluate a +constant expression that had to be evaluated. Attempting to divide by 0 +or causing an integer overflow are two ways to induce this error. + Ensure that the expressions given can be evaluated as the desired integer type. See the FFI section of the Reference for more information about using a custom integer type: diff --git a/src/librustc_error_codes/error_codes/E0081.md b/src/librustc_error_codes/error_codes/E0081.md index ec88ca9765e29..fd5eca68e21fd 100644 --- a/src/librustc_error_codes/error_codes/E0081.md +++ b/src/librustc_error_codes/error_codes/E0081.md @@ -1,21 +1,23 @@ -Enum discriminants are used to differentiate enum variants stored in memory. -This error indicates that the same value was used for two or more variants, -making them impossible to tell apart. +A discrimant value is present more than once. + +Erroneous code example: ```compile_fail,E0081 -// Bad. enum Enum { P = 3, - X = 3, + X = 3, // error! Y = 5, } ``` +Enum discriminants are used to differentiate enum variants stored in memory. +This error indicates that the same value was used for two or more variants, +making it impossible to distinguish them. + ``` -// Good. enum Enum { P, - X = 3, + X = 3, // ok! Y = 5, } ``` @@ -27,7 +29,7 @@ variants. ```compile_fail,E0081 enum Bad { X, - Y = 0 + Y = 0, // error! } ``` diff --git a/src/librustc_error_codes/error_codes/E0091.md b/src/librustc_error_codes/error_codes/E0091.md index 2a092402429f1..03cb32803715e 100644 --- a/src/librustc_error_codes/error_codes/E0091.md +++ b/src/librustc_error_codes/error_codes/E0091.md @@ -1,5 +1,6 @@ -You gave an unnecessary type or const parameter in a type alias. Erroneous -code example: +An unnecessary type or const parameter was given in a type alias. + +Erroneous code example: ```compile_fail,E0091 type Foo = u32; // error: type parameter `T` is unused diff --git a/src/librustc_interface/interface.rs b/src/librustc_interface/interface.rs index 70ed4aad7b4aa..beb2465bd4a1a 100644 --- a/src/librustc_interface/interface.rs +++ b/src/librustc_interface/interface.rs @@ -1,4 +1,3 @@ -use crate::queries::Queries; use crate::util; pub use crate::passes::BoxedResolver; @@ -36,7 +35,6 @@ pub struct Compiler { pub(crate) input_path: Option, pub(crate) output_dir: Option, pub(crate) output_file: Option, - pub(crate) queries: Queries, pub(crate) crate_name: Option, pub(crate) register_lints: Option>, pub(crate) override_queries: @@ -169,7 +167,6 @@ pub fn run_compiler_in_existing_thread_pool( input_path: config.input_path, output_dir: config.output_dir, output_file: config.output_file, - queries: Default::default(), crate_name: config.crate_name, register_lints: config.register_lints, override_queries: config.override_queries, diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 5f00bebced35a..e953a64f1906f 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -3,6 +3,7 @@ use crate::util; use crate::proc_macro_decls; use log::{info, warn, log_enabled}; +use rustc::arena::Arena; use rustc::dep_graph::DepGraph; use rustc::hir; use rustc::hir::lowering::lower_crate; @@ -22,7 +23,7 @@ use rustc_codegen_ssa::back::link::emit_metadata; use rustc_codegen_utils::codegen_backend::CodegenBackend; use rustc_codegen_utils::link::filename_for_metadata; use rustc_data_structures::{box_region_allow_access, declare_box_region_type, parallel}; -use rustc_data_structures::sync::{Lrc, ParallelIterator, par_iter}; +use rustc_data_structures::sync::{Lrc, Once, ParallelIterator, par_iter, WorkerLocal}; use rustc_errors::PResult; use rustc_incremental; use rustc_mir as mir; @@ -739,93 +740,77 @@ pub fn default_provide_extern(providers: &mut ty::query::Providers<'_>) { rustc_codegen_ssa::provide_extern(providers); } -declare_box_region_type!( - pub BoxedGlobalCtxt, - for('tcx), - (&'tcx GlobalCtxt<'tcx>) -> ((), ()) -); +pub struct QueryContext<'tcx>(&'tcx GlobalCtxt<'tcx>); -impl BoxedGlobalCtxt { +impl<'tcx> QueryContext<'tcx> { pub fn enter(&mut self, f: F) -> R where - F: for<'tcx> FnOnce(TyCtxt<'tcx>) -> R, + F: FnOnce(TyCtxt<'tcx>) -> R, { - self.access(|gcx| ty::tls::enter_global(gcx, |tcx| f(tcx))) + ty::tls::enter_global(self.0, |tcx| f(tcx)) + } + + pub fn print_stats(&self) { + self.0.queries.print_stats() } } -pub fn create_global_ctxt( - compiler: &Compiler, +pub fn create_global_ctxt<'tcx>( + compiler: &'tcx Compiler, lint_store: Lrc, - mut hir_forest: hir::map::Forest, + hir_forest: &'tcx hir::map::Forest, mut resolver_outputs: ResolverOutputs, outputs: OutputFilenames, crate_name: &str, -) -> BoxedGlobalCtxt { - let sess = compiler.session().clone(); - let codegen_backend = compiler.codegen_backend().clone(); - let crate_name = crate_name.to_string(); + global_ctxt: &'tcx Once>, + all_arenas: &'tcx AllArenas, + arena: &'tcx WorkerLocal>, +) -> QueryContext<'tcx> { + let sess = &compiler.session(); let defs = mem::take(&mut resolver_outputs.definitions); - let override_queries = compiler.override_queries; - - let ((), result) = BoxedGlobalCtxt::new(static move || { - let sess = &*sess; - - let global_ctxt: Option>; - let arenas = AllArenas::new(); - - // Construct the HIR map. - let hir_map = time(sess, "indexing HIR", || { - hir::map::map_crate(sess, &*resolver_outputs.cstore, &mut hir_forest, &defs) - }); - - let query_result_on_disk_cache = time(sess, "load query result cache", || { - rustc_incremental::load_query_result_cache(sess) - }); - let mut local_providers = ty::query::Providers::default(); - default_provide(&mut local_providers); - codegen_backend.provide(&mut local_providers); + // Construct the HIR map. + let hir_map = time(sess, "indexing HIR", || { + hir::map::map_crate(sess, &*resolver_outputs.cstore, &hir_forest, defs) + }); - let mut extern_providers = local_providers; - default_provide_extern(&mut extern_providers); - codegen_backend.provide_extern(&mut extern_providers); + let query_result_on_disk_cache = time(sess, "load query result cache", || { + rustc_incremental::load_query_result_cache(sess) + }); - if let Some(callback) = override_queries { - callback(sess, &mut local_providers, &mut extern_providers); - } + let codegen_backend = compiler.codegen_backend(); + let mut local_providers = ty::query::Providers::default(); + default_provide(&mut local_providers); + codegen_backend.provide(&mut local_providers); - let gcx = TyCtxt::create_global_ctxt( - sess, - lint_store, - local_providers, - extern_providers, - &arenas, - resolver_outputs, - hir_map, - query_result_on_disk_cache, - &crate_name, - &outputs - ); + let mut extern_providers = local_providers; + default_provide_extern(&mut extern_providers); + codegen_backend.provide_extern(&mut extern_providers); - global_ctxt = Some(gcx); - let gcx = global_ctxt.as_ref().unwrap(); - - ty::tls::enter_global(gcx, |tcx| { - // Do some initialization of the DepGraph that can only be done with the - // tcx available. - time(tcx.sess, "dep graph tcx init", || rustc_incremental::dep_graph_tcx_init(tcx)); - }); + if let Some(callback) = compiler.override_queries { + callback(sess, &mut local_providers, &mut extern_providers); + } - yield BoxedGlobalCtxt::initial_yield(()); - box_region_allow_access!(for('tcx), (&'tcx GlobalCtxt<'tcx>), (gcx)); + let gcx = global_ctxt.init_locking(|| TyCtxt::create_global_ctxt( + sess, + lint_store, + local_providers, + extern_providers, + &all_arenas, + arena, + resolver_outputs, + hir_map, + query_result_on_disk_cache, + &crate_name, + &outputs + )); - if sess.opts.debugging_opts.query_stats { - gcx.queries.print_stats(); - } + // Do some initialization of the DepGraph that can only be done with the tcx available. + ty::tls::enter_global(&gcx, |tcx| { + time(tcx.sess, "dep graph tcx init", || rustc_incremental::dep_graph_tcx_init(tcx)); }); - result + QueryContext(gcx) } /// Runs the resolution, type-checking, region checking and other diff --git a/src/librustc_interface/queries.rs b/src/librustc_interface/queries.rs index 9094f36d44e5e..6103d42c5dbcb 100644 --- a/src/librustc_interface/queries.rs +++ b/src/librustc_interface/queries.rs @@ -1,17 +1,19 @@ use crate::interface::{Compiler, Result}; -use crate::passes::{self, BoxedResolver, BoxedGlobalCtxt}; +use crate::passes::{self, BoxedResolver, QueryContext}; use rustc_incremental::DepGraphFuture; -use rustc_data_structures::sync::Lrc; +use rustc_data_structures::sync::{Lrc, Once, WorkerLocal}; +use rustc_codegen_utils::codegen_backend::CodegenBackend; use rustc::session::config::{OutputFilenames, OutputType}; use rustc::util::common::{time, ErrorReported}; +use rustc::arena::Arena; use rustc::hir; use rustc::lint; use rustc::session::Session; use rustc::lint::LintStore; use rustc::hir::def_id::LOCAL_CRATE; use rustc::ty::steal::Steal; -use rustc::ty::ResolverOutputs; +use rustc::ty::{AllArenas, ResolverOutputs, GlobalCtxt}; use rustc::dep_graph::DepGraph; use std::cell::{Ref, RefMut, RefCell}; use std::rc::Rc; @@ -44,13 +46,6 @@ impl Query { .unwrap() } - /// Returns a stolen query result. Panics if there's already a result. - pub fn give(&self, value: T) { - let mut result = self.result.borrow_mut(); - assert!(result.is_none(), "a result already exists"); - *result = Some(Ok(value)); - } - /// Borrows the query result using the RefCell. Panics if the result is stolen. pub fn peek(&self) -> Ref<'_, T> { Ref::map(self.result.borrow(), |r| { @@ -74,24 +69,54 @@ impl Default for Query { } } -#[derive(Default)] -pub(crate) struct Queries { +pub struct Queries<'tcx> { + compiler: &'tcx Compiler, + gcx: Once>, + + all_arenas: AllArenas, + arena: WorkerLocal>, + dep_graph_future: Query>, parse: Query, crate_name: Query, register_plugins: Query<(ast::Crate, Lrc)>, expansion: Query<(ast::Crate, Steal>>, Lrc)>, dep_graph: Query, - lower_to_hir: Query<(Steal, Steal)>, + lower_to_hir: Query<(&'tcx hir::map::Forest, Steal)>, prepare_outputs: Query, - global_ctxt: Query, + global_ctxt: Query>, ongoing_codegen: Query>, - link: Query<()>, } -impl Compiler { +impl<'tcx> Queries<'tcx> { + pub fn new(compiler: &'tcx Compiler) -> Queries<'tcx> { + Queries { + compiler, + gcx: Once::new(), + all_arenas: AllArenas::new(), + arena: WorkerLocal::new(|_| Arena::default()), + dep_graph_future: Default::default(), + parse: Default::default(), + crate_name: Default::default(), + register_plugins: Default::default(), + expansion: Default::default(), + dep_graph: Default::default(), + lower_to_hir: Default::default(), + prepare_outputs: Default::default(), + global_ctxt: Default::default(), + ongoing_codegen: Default::default(), + } + } + + fn session(&self) -> &Lrc { + &self.compiler.sess + } + fn codegen_backend(&self) -> &Lrc> { + &self.compiler.codegen_backend() + } + pub fn dep_graph_future(&self) -> Result<&Query>> { - self.queries.dep_graph_future.compute(|| { + self.dep_graph_future.compute(|| { Ok(if self.session().opts.build_dep_graph() { Some(rustc_incremental::load_dep_graph(self.session())) } else { @@ -101,8 +126,8 @@ impl Compiler { } pub fn parse(&self) -> Result<&Query> { - self.queries.parse.compute(|| { - passes::parse(self.session(), &self.input).map_err( + self.parse.compute(|| { + passes::parse(self.session(), &self.compiler.input).map_err( |mut parse_error| { parse_error.emit(); ErrorReported @@ -112,7 +137,7 @@ impl Compiler { } pub fn register_plugins(&self) -> Result<&Query<(ast::Crate, Lrc)>> { - self.queries.register_plugins.compute(|| { + self.register_plugins.compute(|| { let crate_name = self.crate_name()?.peek().clone(); let krate = self.parse()?.take(); @@ -120,7 +145,7 @@ impl Compiler { let result = passes::register_plugins( self.session(), &*self.codegen_backend().metadata_loader(), - self.register_lints + self.compiler.register_lints .as_ref() .map(|p| &**p) .unwrap_or_else(|| empty), @@ -140,8 +165,8 @@ impl Compiler { } pub fn crate_name(&self) -> Result<&Query> { - self.queries.crate_name.compute(|| { - Ok(match self.crate_name { + self.crate_name.compute(|| { + Ok(match self.compiler.crate_name { Some(ref crate_name) => crate_name.clone(), None => { let parse_result = self.parse()?; @@ -149,7 +174,7 @@ impl Compiler { rustc_codegen_utils::link::find_crate_name( Some(self.session()), &krate.attrs, - &self.input + &self.compiler.input ) } }) @@ -159,11 +184,11 @@ impl Compiler { pub fn expansion( &self ) -> Result<&Query<(ast::Crate, Steal>>, Lrc)>> { - self.queries.expansion.compute(|| { + self.expansion.compute(|| { let crate_name = self.crate_name()?.peek().clone(); let (krate, lint_store) = self.register_plugins()?.take(); passes::configure_and_expand( - self.sess.clone(), + self.session().clone(), lint_store.clone(), self.codegen_backend().metadata_loader(), krate, @@ -175,7 +200,7 @@ impl Compiler { } pub fn dep_graph(&self) -> Result<&Query> { - self.queries.dep_graph.compute(|| { + self.dep_graph.compute(|| { Ok(match self.dep_graph_future()?.take() { None => DepGraph::new_disabled(), Some(future) => { @@ -192,15 +217,15 @@ impl Compiler { } pub fn lower_to_hir( - &self, - ) -> Result<&Query<(Steal, Steal)>> { - self.queries.lower_to_hir.compute(|| { + &'tcx self, + ) -> Result<&Query<(&'tcx hir::map::Forest, Steal)>> { + self.lower_to_hir.compute(|| { let expansion_result = self.expansion()?; let peeked = expansion_result.peek(); let krate = &peeked.0; let resolver = peeked.1.steal(); let lint_store = &peeked.2; - let hir = Steal::new(resolver.borrow_mut().access(|resolver| { + let hir = resolver.borrow_mut().access(|resolver| { passes::lower_to_hir( self.session(), lint_store, @@ -208,41 +233,47 @@ impl Compiler { &*self.dep_graph()?.peek(), &krate ) - })?); + })?; + let hir = self.arena.alloc(hir); Ok((hir, Steal::new(BoxedResolver::to_resolver_outputs(resolver)))) }) } pub fn prepare_outputs(&self) -> Result<&Query> { - self.queries.prepare_outputs.compute(|| { + self.prepare_outputs.compute(|| { let expansion_result = self.expansion()?; let (krate, boxed_resolver, _) = &*expansion_result.peek(); let crate_name = self.crate_name()?; let crate_name = crate_name.peek(); - passes::prepare_outputs(self.session(), self, &krate, &boxed_resolver, &crate_name) + passes::prepare_outputs( + self.session(), self.compiler, &krate, &boxed_resolver, &crate_name + ) }) } - pub fn global_ctxt(&self) -> Result<&Query> { - self.queries.global_ctxt.compute(|| { + pub fn global_ctxt(&'tcx self) -> Result<&Query>> { + self.global_ctxt.compute(|| { let crate_name = self.crate_name()?.peek().clone(); let outputs = self.prepare_outputs()?.peek().clone(); let lint_store = self.expansion()?.peek().2.clone(); - let hir = self.lower_to_hir()?; - let hir = hir.peek(); - let (hir_forest, resolver_outputs) = &*hir; + let hir = self.lower_to_hir()?.peek(); + let (ref hir_forest, ref resolver_outputs) = &*hir; Ok(passes::create_global_ctxt( - self, + self.compiler, lint_store, - hir_forest.steal(), + hir_forest, resolver_outputs.steal(), outputs, - &crate_name)) + &crate_name, + &self.gcx, + &self.all_arenas, + &self.arena, + )) }) } - pub fn ongoing_codegen(&self) -> Result<&Query>> { - self.queries.ongoing_codegen.compute(|| { + pub fn ongoing_codegen(&'tcx self) -> Result<&Query>> { + self.ongoing_codegen.compute(|| { let outputs = self.prepare_outputs()?; self.global_ctxt()?.peek_mut().enter(|tcx| { tcx.analysis(LOCAL_CRATE).ok(); @@ -259,22 +290,58 @@ impl Compiler { }) } - pub fn link(&self) -> Result<&Query<()>> { - self.queries.link.compute(|| { - let sess = self.session(); - - let ongoing_codegen = self.ongoing_codegen()?.take(); + pub fn linker(&'tcx self) -> Result { + let dep_graph = self.dep_graph()?; + let prepare_outputs = self.prepare_outputs()?; + let ongoing_codegen = self.ongoing_codegen()?; - self.codegen_backend().join_codegen_and_link( - ongoing_codegen, - sess, - &*self.dep_graph()?.peek(), - &*self.prepare_outputs()?.peek(), - ).map_err(|_| ErrorReported)?; + let sess = self.session().clone(); + let codegen_backend = self.codegen_backend().clone(); - Ok(()) + Ok(Linker { + sess, + dep_graph: dep_graph.peek().clone(), + prepare_outputs: prepare_outputs.take(), + ongoing_codegen: ongoing_codegen.take(), + codegen_backend, }) } +} + +pub struct Linker { + sess: Lrc, + dep_graph: DepGraph, + prepare_outputs: OutputFilenames, + ongoing_codegen: Box, + codegen_backend: Lrc>, +} + +impl Linker { + pub fn link(self) -> Result<()> { + self.codegen_backend.join_codegen_and_link( + self.ongoing_codegen, + &self.sess, + &self.dep_graph, + &self.prepare_outputs, + ).map_err(|_| ErrorReported) + } +} + +impl Compiler { + pub fn enter(&self, f: F) -> T + where F: for<'tcx> FnOnce(&'tcx Queries<'tcx>) -> T + { + let queries = Queries::new(&self); + let ret = f(&queries); + + if self.session().opts.debugging_opts.query_stats { + if let Ok(gcx) = queries.global_ctxt() { + gcx.peek().print_stats(); + } + } + + ret + } // This method is different to all the other methods in `Compiler` because // it lacks a `Queries` entry. It's also not currently used. It does serve @@ -282,24 +349,30 @@ impl Compiler { // between some passes. And see `rustc_driver::run_compiler` for a more // complex example. pub fn compile(&self) -> Result<()> { - self.prepare_outputs()?; + let linker = self.enter(|queries| { + queries.prepare_outputs()?; - if self.session().opts.output_types.contains_key(&OutputType::DepInfo) - && self.session().opts.output_types.len() == 1 - { - return Ok(()) - } + if self.session().opts.output_types.contains_key(&OutputType::DepInfo) + && self.session().opts.output_types.len() == 1 + { + return Ok(None) + } + + queries.global_ctxt()?; - self.global_ctxt()?; + // Drop AST after creating GlobalCtxt to free memory. + mem::drop(queries.expansion()?.take()); - // Drop AST after creating GlobalCtxt to free memory. - mem::drop(self.expansion()?.take()); + queries.ongoing_codegen()?; - self.ongoing_codegen()?; + let linker = queries.linker()?; + Ok(Some(linker)) + })?; - // Drop GlobalCtxt after starting codegen to free memory. - mem::drop(self.global_ctxt()?.take()); + if let Some(linker) = linker { + linker.link()? + } - self.link().map(|_| ()) + Ok(()) } } diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 649aeac12de94..3a783f674e9ae 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -300,11 +300,10 @@ fn do_mir_borrowck<'a, 'tcx>( let mut initial_diag = mbcx.report_conflicting_borrow(location, (&place, span), bk, &borrow); - let lint_root = if let ClearCrossCrate::Set(ref vsi) = mbcx.body.source_scope_local_data { - let scope = mbcx.body.source_info(location).scope; - vsi[scope].lint_root - } else { - id + let scope = mbcx.body.source_info(location).scope; + let lint_root = match &mbcx.body.source_scopes[scope].local_data { + ClearCrossCrate::Set(data) => data.lint_root, + _ => id, }; // Span and message don't matter; we overwrite them below anyway @@ -338,38 +337,40 @@ fn do_mir_borrowck<'a, 'tcx>( debug!("mbcx.used_mut: {:?}", mbcx.used_mut); let used_mut = mbcx.used_mut; for local in mbcx.body.mut_vars_and_args_iter().filter(|local| !used_mut.contains(local)) { - if let ClearCrossCrate::Set(ref vsi) = mbcx.body.source_scope_local_data { - let local_decl = &mbcx.body.local_decls[local]; - - // Skip over locals that begin with an underscore or have no name - match mbcx.local_names[local] { - Some(name) => if name.as_str().starts_with("_") { - continue; - }, - None => continue, - } + let local_decl = &mbcx.body.local_decls[local]; + let lint_root = match &mbcx.body.source_scopes[local_decl.source_info.scope].local_data { + ClearCrossCrate::Set(data) => data.lint_root, + _ => continue, + }; - let span = local_decl.source_info.span; - if span.desugaring_kind().is_some() { - // If the `mut` arises as part of a desugaring, we should ignore it. + // Skip over locals that begin with an underscore or have no name + match mbcx.local_names[local] { + Some(name) => if name.as_str().starts_with("_") { continue; - } + }, + None => continue, + } - let mut_span = tcx.sess.source_map().span_until_non_whitespace(span); - tcx.struct_span_lint_hir( - UNUSED_MUT, - vsi[local_decl.source_info.scope].lint_root, - span, - "variable does not need to be mutable", - ) - .span_suggestion_short( - mut_span, - "remove this `mut`", - String::new(), - Applicability::MachineApplicable, - ) - .emit(); + let span = local_decl.source_info.span; + if span.desugaring_kind().is_some() { + // If the `mut` arises as part of a desugaring, we should ignore it. + continue; } + + let mut_span = tcx.sess.source_map().span_until_non_whitespace(span); + tcx.struct_span_lint_hir( + UNUSED_MUT, + lint_root, + span, + "variable does not need to be mutable", + ) + .span_suggestion_short( + mut_span, + "remove this `mut`", + String::new(), + Applicability::MachineApplicable, + ) + .emit(); } // Buffer any move errors that we collected and de-duplicated. diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 180f2cc089f02..775a50f10ff32 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -309,7 +309,6 @@ struct Builder<'a, 'tcx> { /// The vector of all scopes that we have created thus far; /// we track this for debuginfo later. source_scopes: IndexVec, - source_scope_local_data: IndexVec, source_scope: SourceScope, /// The guard-context: each time we build the guard expression for @@ -704,7 +703,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block_context: BlockContext::new(), source_scopes: IndexVec::new(), source_scope: OUTERMOST_SOURCE_SCOPE, - source_scope_local_data: IndexVec::new(), guard_context: vec![], push_unsafe_count: 0, unpushed_unsafe: safety, @@ -741,7 +739,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Body::new( self.cfg.basic_blocks, self.source_scopes, - ClearCrossCrate::Set(self.source_scope_local_data), self.local_decls, self.canonical_user_type_annotations, self.arg_count, @@ -941,7 +938,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.hir.root_lint_level ); let parent_root = tcx.maybe_lint_level_root_bounded( - self.source_scope_local_data[original_source_scope].lint_root, + self.source_scopes[original_source_scope] + .local_data + .as_ref() + .assert_crate_local() + .lint_root, self.hir.root_lint_level, ); if current_root != parent_root { diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index 1b3d8641f204e..78e642e4348f7 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -430,7 +430,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // We estimate the true lint roots here to avoid creating a lot of source scopes. let parent_root = tcx.maybe_lint_level_root_bounded( - self.source_scope_local_data[source_scope].lint_root, + self.source_scopes[source_scope] + .local_data + .as_ref() + .assert_crate_local() + .lint_root, self.hir.root_lint_level, ); let current_root = tcx.maybe_lint_level_root_bounded( @@ -648,23 +652,22 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let parent = self.source_scope; debug!("new_source_scope({:?}, {:?}, {:?}) - parent({:?})={:?}", span, lint_level, safety, - parent, self.source_scope_local_data.get(parent)); - let scope = self.source_scopes.push(SourceScopeData { - span, - parent_scope: Some(parent), - }); + parent, self.source_scopes.get(parent)); let scope_local_data = SourceScopeLocalData { lint_root: if let LintLevel::Explicit(lint_root) = lint_level { lint_root } else { - self.source_scope_local_data[parent].lint_root + self.source_scopes[parent].local_data.as_ref().assert_crate_local().lint_root }, safety: safety.unwrap_or_else(|| { - self.source_scope_local_data[parent].safety + self.source_scopes[parent].local_data.as_ref().assert_crate_local().safety }) }; - self.source_scope_local_data.push(scope_local_data); - scope + self.source_scopes.push(SourceScopeData { + span, + parent_scope: Some(parent), + local_data: ClearCrossCrate::Set(scope_local_data), + }) } /// Given a span and the current source scope, make a SourceInfo. diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index afc4e461c0df5..8c852854be1f9 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -933,14 +933,7 @@ fn convert_path_expr<'a, 'tcx>( // We encode uses of statics as a `*&STATIC` where the `&STATIC` part is // a constant reference (or constant raw pointer for `static mut`) in MIR Res::Def(DefKind::Static, id) => { - let ty = cx.tcx.type_of(id); - let ty = if cx.tcx.is_mutable_static(id) { - cx.tcx.mk_mut_ptr(ty) - } else if cx.tcx.is_foreign_item(id) { - cx.tcx.mk_imm_ptr(ty) - } else { - cx.tcx.mk_imm_ref(cx.tcx.lifetimes.re_static, ty) - }; + let ty = cx.tcx.static_ptr_ty(id); let ptr = cx.tcx.alloc_map.lock().create_static_alloc(id); let temp_lifetime = cx.region_scope_tree.temporary_scope(expr.hir_id.local_id); ExprKind::Deref { arg: Expr { diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 626e81fa91186..dc62cbefe3442 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -849,8 +849,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } else { block.terminator().source_info }; - match body.source_scope_local_data { - mir::ClearCrossCrate::Set(ref ivs) => Some(ivs[source_info.scope].lint_root), + match &body.source_scopes[source_info.scope].local_data { + mir::ClearCrossCrate::Set(data) => Some(data.lint_root), mir::ClearCrossCrate::Clear => None, } }); diff --git a/src/librustc_mir/interpret/intern.rs b/src/librustc_mir/interpret/intern.rs index 630f3f603449b..f9cb40ffe9446 100644 --- a/src/librustc_mir/interpret/intern.rs +++ b/src/librustc_mir/interpret/intern.rs @@ -100,7 +100,7 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>>( // This match is just a canary for future changes to `MemoryKind`, which most likely need // changes in this function. match kind { - MemoryKind::Stack | MemoryKind::Vtable => {}, + MemoryKind::Stack | MemoryKind::Vtable | MemoryKind::CallerLocation => {}, } // Set allocation mutability as appropriate. This is used by LLVM to put things into // read-only memory, and also by Miri when evluating other constants/statics that diff --git a/src/librustc_mir/interpret/intrinsics/caller_location.rs b/src/librustc_mir/interpret/intrinsics/caller_location.rs index 88bfcd63129fa..9e07a3f1072c1 100644 --- a/src/librustc_mir/interpret/intrinsics/caller_location.rs +++ b/src/librustc_mir/interpret/intrinsics/caller_location.rs @@ -28,7 +28,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let file = Scalar::Ptr(self.tag_static_base_pointer(file_ptr)); let file_len = Scalar::from_uint(filename.as_str().len() as u128, ptr_size); - let location = self.allocate(loc_layout, MemoryKind::Stack); + let location = self.allocate(loc_layout, MemoryKind::CallerLocation); let file_out = self.mplace_field(location, 0)?; let file_ptr_out = self.force_ptr(self.mplace_field(file_out, 0)?.ptr)?; diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index eccdc5b03261b..a8011f7abb14f 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -24,11 +24,13 @@ use super::{ #[derive(Debug, PartialEq, Copy, Clone)] pub enum MemoryKind { - /// Error if deallocated except during a stack pop + /// Stack memory. Error if deallocated except during a stack pop. Stack, - /// Error if ever deallocated + /// Memory backing vtables. Error if ever deallocated. Vtable, - /// Additional memory kinds a machine wishes to distinguish from the builtin ones + /// Memory allocated by `caller_location` intrinsic. Error if ever deallocated. + CallerLocation, + /// Additional memory kinds a machine wishes to distinguish from the builtin ones. Machine(T), } @@ -38,6 +40,7 @@ impl MayLeak for MemoryKind { match self { MemoryKind::Stack => false, MemoryKind::Vtable => true, + MemoryKind::CallerLocation => true, MemoryKind::Machine(k) => k.may_leak() } } @@ -719,6 +722,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { let extra = match kind { MemoryKind::Stack => " (stack)".to_owned(), MemoryKind::Vtable => " (vtable)".to_owned(), + MemoryKind::CallerLocation => " (caller_location)".to_owned(), MemoryKind::Machine(m) => format!(" ({:?})", m), }; self.dump_alloc_helper( diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index b5cb6a92816be..b1b7b36323620 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -199,9 +199,9 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option>) let mut body = Body::new( blocks, IndexVec::from_elem_n( - SourceScopeData { span: span, parent_scope: None }, 1 + SourceScopeData { span, parent_scope: None, local_data: ClearCrossCrate::Clear }, + 1, ), - ClearCrossCrate::Clear, local_decls_for_sig(&sig, span), IndexVec::new(), sig.inputs().len(), @@ -365,9 +365,13 @@ impl CloneShimBuilder<'tcx> { Body::new( self.blocks, IndexVec::from_elem_n( - SourceScopeData { span: self.span, parent_scope: None }, 1 + SourceScopeData { + span: self.span, + parent_scope: None, + local_data: ClearCrossCrate::Clear, + }, + 1, ), - ClearCrossCrate::Clear, self.local_decls, IndexVec::new(), self.sig.inputs().len(), @@ -825,9 +829,9 @@ fn build_call_shim<'tcx>( let mut body = Body::new( blocks, IndexVec::from_elem_n( - SourceScopeData { span: span, parent_scope: None }, 1 + SourceScopeData { span, parent_scope: None, local_data: ClearCrossCrate::Clear }, + 1, ), - ClearCrossCrate::Clear, local_decls, IndexVec::new(), sig.inputs().len(), @@ -911,9 +915,9 @@ pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> &Body<'_> { let body = Body::new( IndexVec::from_elem_n(start_block, 1), IndexVec::from_elem_n( - SourceScopeData { span: span, parent_scope: None }, 1 + SourceScopeData { span, parent_scope: None, local_data: ClearCrossCrate::Clear }, + 1, ), - ClearCrossCrate::Clear, local_decls, IndexVec::new(), sig.inputs().len(), diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index b7cc4e9fcf66c..d12d21aee6abe 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -1,6 +1,4 @@ use rustc_data_structures::fx::FxHashSet; -use rustc_index::vec::IndexVec; -use rustc_data_structures::sync::Lrc; use rustc::ty::query::Providers; use rustc::ty::{self, TyCtxt}; @@ -24,7 +22,6 @@ pub struct UnsafetyChecker<'a, 'tcx> { body: &'a Body<'tcx>, const_context: bool, min_const_fn: bool, - source_scope_local_data: &'a IndexVec, violations: Vec, source_info: SourceInfo, tcx: TyCtxt<'tcx>, @@ -39,7 +36,6 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { const_context: bool, min_const_fn: bool, body: &'a Body<'tcx>, - source_scope_local_data: &'a IndexVec, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, ) -> Self { @@ -51,7 +47,6 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { body, const_context, min_const_fn, - source_scope_local_data, violations: vec![], source_info: SourceInfo { span: body.span, @@ -219,8 +214,11 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { if context.is_borrow() { if util::is_disaligned(self.tcx, self.body, self.param_env, place) { let source_info = self.source_info; - let lint_root = - self.source_scope_local_data[source_info.scope].lint_root; + let lint_root = self.body.source_scopes[source_info.scope] + .local_data + .as_ref() + .assert_crate_local() + .lint_root; self.register_violations(&[UnsafetyViolation { source_info, description: Symbol::intern("borrow of packed field"), @@ -346,7 +344,11 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { fn register_violations(&mut self, violations: &[UnsafetyViolation], unsafe_blocks: &[(hir::HirId, bool)]) { - let safety = self.source_scope_local_data[self.source_info.scope].safety; + let safety = self.body.source_scopes[self.source_info.scope] + .local_data + .as_ref() + .assert_crate_local() + .safety; let within_unsafe = match safety { // `unsafe` blocks are required in safe code Safety::Safe => { @@ -516,17 +518,6 @@ fn unsafety_check_result(tcx: TyCtxt<'_>, def_id: DefId) -> UnsafetyCheckResult // `mir_built` force this. let body = &tcx.mir_built(def_id).borrow(); - let source_scope_local_data = match body.source_scope_local_data { - ClearCrossCrate::Set(ref data) => data, - ClearCrossCrate::Clear => { - debug!("unsafety_violations: {:?} - remote, skipping", def_id); - return UnsafetyCheckResult { - violations: Lrc::new([]), - unsafe_blocks: Lrc::new([]) - } - } - }; - let param_env = tcx.param_env(def_id); let id = tcx.hir().as_local_hir_id(def_id).unwrap(); @@ -536,9 +527,7 @@ fn unsafety_check_result(tcx: TyCtxt<'_>, def_id: DefId) -> UnsafetyCheckResult hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) => (true, false), }; - let mut checker = UnsafetyChecker::new( - const_context, min_const_fn, - body, source_scope_local_data, tcx, param_env); + let mut checker = UnsafetyChecker::new(const_context, min_const_fn, body, tcx, param_env); checker.visit_body(body); check_unused_unsafe(tcx, def_id, &checker.used_unsafe, &mut checker.inherited_blocks); diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 8de16308e8375..dcea886c2b607 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -9,7 +9,7 @@ use rustc::hir::def_id::DefId; use rustc::mir::{ AggregateKind, Constant, Location, Place, PlaceBase, Body, Operand, Rvalue, Local, UnOp, StatementKind, Statement, LocalKind, TerminatorKind, Terminator, ClearCrossCrate, SourceInfo, - BinOp, SourceScope, SourceScopeLocalData, LocalDecl, BasicBlock, RETURN_PLACE, + BinOp, SourceScope, SourceScopeData, LocalDecl, BasicBlock, RETURN_PLACE, }; use rustc::mir::visit::{ Visitor, PlaceContext, MutatingUseContext, MutVisitor, NonMutatingUseContext, @@ -74,17 +74,10 @@ impl<'tcx> MirPass<'tcx> for ConstProp { trace!("ConstProp starting for {:?}", source.def_id()); - // Steal some data we need from `body`. - let source_scope_local_data = std::mem::replace( - &mut body.source_scope_local_data, - ClearCrossCrate::Clear - ); - let dummy_body = &Body::new( body.basic_blocks().clone(), - Default::default(), - ClearCrossCrate::Clear, + body.source_scopes.clone(), body.local_decls.clone(), Default::default(), body.arg_count, @@ -100,19 +93,11 @@ impl<'tcx> MirPass<'tcx> for ConstProp { let mut optimization_finder = ConstPropagator::new( body, dummy_body, - source_scope_local_data, tcx, source ); optimization_finder.visit_body(body); - // put back the data we stole from `mir` - let source_scope_local_data = optimization_finder.release_stolen_data(); - std::mem::replace( - &mut body.source_scope_local_data, - source_scope_local_data - ); - trace!("ConstProp done for {:?}", source.def_id()); } } @@ -265,7 +250,9 @@ struct ConstPropagator<'mir, 'tcx> { source: MirSource<'tcx>, can_const_prop: IndexVec, param_env: ParamEnv<'tcx>, - source_scope_local_data: ClearCrossCrate>, + // FIXME(eddyb) avoid cloning these two fields more than once, + // by accessing them through `ecx` instead. + source_scopes: IndexVec, local_decls: IndexVec>, ret: Option>, } @@ -297,7 +284,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { fn new( body: &Body<'tcx>, dummy_body: &'mir Body<'tcx>, - source_scope_local_data: ClearCrossCrate>, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, ) -> ConstPropagator<'mir, 'tcx> { @@ -335,17 +321,15 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { source, param_env, can_const_prop, - source_scope_local_data, + // FIXME(eddyb) avoid cloning these two fields more than once, + // by accessing them through `ecx` instead. + source_scopes: body.source_scopes.clone(), //FIXME(wesleywiser) we can't steal this because `Visitor::super_visit_body()` needs it local_decls: body.local_decls.clone(), ret: ret.map(Into::into), } } - fn release_stolen_data(self) -> ClearCrossCrate> { - self.source_scope_local_data - } - fn get_const(&self, local: Local) -> Option> { if local == RETURN_PLACE { // Try to read the return place as an immediate so that if it is representable as a @@ -375,14 +359,11 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { F: FnOnce(&mut Self) -> InterpResult<'tcx, T>, { self.ecx.tcx.span = source_info.span; - let lint_root = match self.source_scope_local_data { - ClearCrossCrate::Set(ref ivs) => { - //FIXME(#51314): remove this check - if source_info.scope.index() >= ivs.len() { - return None; - } - ivs[source_info.scope].lint_root - }, + // FIXME(eddyb) move this to the `Panic(_)` error case, so that + // `f(self)` is always called, and that the only difference when the + // scope's `local_data` is missing, is that the lint isn't emitted. + let lint_root = match &self.source_scopes[source_info.scope].local_data { + ClearCrossCrate::Set(data) => data.lint_root, ClearCrossCrate::Clear => return None, }; let r = match f(self) { @@ -506,8 +487,8 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { let right_size = r.layout.size; let r_bits = r.to_scalar().and_then(|r| r.to_bits(right_size)); if r_bits.ok().map_or(false, |b| b >= left_bits as u128) { - let source_scope_local_data = match self.source_scope_local_data { - ClearCrossCrate::Set(ref data) => data, + let lint_root = match &self.source_scopes[source_info.scope].local_data { + ClearCrossCrate::Set(data) => data.lint_root, ClearCrossCrate::Clear => return None, }; let dir = if *op == BinOp::Shr { @@ -515,10 +496,9 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } else { "left" }; - let hir_id = source_scope_local_data[source_info.scope].lint_root; self.tcx.lint_hir( ::rustc::lint::builtin::EXCEEDING_BITSHIFTS, - hir_id, + lint_root, span, &format!("attempt to shift {} with overflow", dir)); return None; diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index 867673beb35cc..ebfadd0cfd3ed 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -391,9 +391,14 @@ impl Inliner<'tcx> { for mut scope in callee_body.source_scopes.iter().cloned() { if scope.parent_scope.is_none() { scope.parent_scope = Some(callsite.location.scope); + // FIXME(eddyb) is this really needed? + // (also note that it's always overwritten below) scope.span = callee_body.span; } + // FIXME(eddyb) this doesn't seem right at all. + // The inlined source scopes should probably be annotated as + // such, but also contain all of the original information. scope.span = callsite.location.span; let idx = caller_body.source_scopes.push(scope); diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index d927ac27fd7ae..a7f2f2a377c08 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -1081,7 +1081,6 @@ pub fn promote_candidates<'tcx>( // FIXME: maybe try to filter this to avoid blowing up // memory usage? body.source_scopes.clone(), - body.source_scope_local_data.clone(), initial_locals, IndexVec::new(), 0, diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 8c4b4c16510bb..fcbc2a3301ad1 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -84,7 +84,7 @@ where { fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> bool { let TraitRef { def_id, substs } = trait_ref; - self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref) || + self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref.print_only_trait_path()) || (!self.def_id_visitor.shallow() && substs.visit_with(self)) } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index a33b2e32c8658..fdbf729a773aa 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1149,8 +1149,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let candidates = traits::supertraits(tcx, trait_ref).filter(|r| { self.trait_defines_associated_type_named(r.def_id(), binding.item_name) }); - self.one_bound_for_assoc_type(candidates, &trait_ref.to_string(), - binding.item_name, binding.span) + self.one_bound_for_assoc_type( + candidates, + &trait_ref.print_only_trait_path().to_string(), + binding.item_name, + binding.span + ) }?; let (assoc_ident, def_scope) = @@ -1589,12 +1593,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { if let Some(span) = bound_span { err.span_label(span, format!("ambiguous `{}` from `{}`", assoc_name, - bound)); + bound.print_only_trait_path())); } else { span_note!(&mut err, span, "associated type `{}` could derive from `{}`", ty_param_name, - bound); + bound.print_only_trait_path()); } } err.emit(); diff --git a/src/librustc_typeck/check/generator_interior.rs b/src/librustc_typeck/check/generator_interior.rs index 6e37c0dbbdf9d..fcf6b22f74f3c 100644 --- a/src/librustc_typeck/check/generator_interior.rs +++ b/src/librustc_typeck/check/generator_interior.rs @@ -185,6 +185,8 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> { } fn visit_expr(&mut self, expr: &'tcx Expr) { + let scope = self.region_scope_tree.temporary_scope(expr.hir_id.local_id); + match &expr.kind { ExprKind::Call(callee, args) => match &callee.kind { ExprKind::Path(qpath) => { @@ -210,13 +212,20 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> { } _ => intravisit::walk_expr(self, expr), } + ExprKind::Path(qpath) => { + let res = self.fcx.tables.borrow().qpath_res(qpath, expr.hir_id); + if let Res::Def(DefKind::Static, def_id) = res { + // Statics are lowered to temporary references or + // pointers in MIR, so record that type. + let ptr_ty = self.fcx.tcx.static_ptr_ty(def_id); + self.record(ptr_ty, scope, Some(expr), expr.span); + } + } _ => intravisit::walk_expr(self, expr), } self.expr_count += 1; - let scope = self.region_scope_tree.temporary_scope(expr.hir_id.local_id); - // If there are adjustments, then record the final type -- // this is the actual value that is being produced. if let Some(adjusted_ty) = self.fcx.tables.borrow().expr_ty_adjusted_opt(expr) { diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 6e37a1a47f061..f4b53b4d10604 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -502,7 +502,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if !unsatisfied_predicates.is_empty() { let mut bound_list = unsatisfied_predicates.iter() - .map(|p| format!("`{} : {}`", p.self_ty(), p)) + .map(|p| format!("`{} : {}`", p.self_ty(), p.print_only_trait_path())) .collect::>(); bound_list.sort(); bound_list.dedup(); // #35677 diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 930241262b0c1..3a4a4a50bf273 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -2002,7 +2002,7 @@ fn check_impl_items_against_trait<'tcx>( "item `{}` is an associated const, \ which doesn't match its trait `{}`", ty_impl_item.ident, - impl_trait_ref); + impl_trait_ref.print_only_trait_path()); err.span_label(impl_item.span, "does not match trait"); // We can only get the spans from local trait definition // Same for E0324 and E0325 @@ -2026,7 +2026,7 @@ fn check_impl_items_against_trait<'tcx>( "item `{}` is an associated method, \ which doesn't match its trait `{}`", ty_impl_item.ident, - impl_trait_ref); + impl_trait_ref.print_only_trait_path()); err.span_label(impl_item.span, "does not match trait"); if let Some(trait_span) = tcx.hir().span_if_local(ty_trait_item.def_id) { err.span_label(trait_span, "item in trait"); @@ -2045,7 +2045,7 @@ fn check_impl_items_against_trait<'tcx>( "item `{}` is an associated type, \ which doesn't match its trait `{}`", ty_impl_item.ident, - impl_trait_ref); + impl_trait_ref.print_only_trait_path()); err.span_label(impl_item.span, "does not match trait"); if let Some(trait_span) = tcx.hir().span_if_local(ty_trait_item.def_id) { err.span_label(trait_span, "item in trait"); diff --git a/src/librustc_typeck/coherence/unsafety.rs b/src/librustc_typeck/coherence/unsafety.rs index 5bb444999681d..650e15ea8a7c8 100644 --- a/src/librustc_typeck/coherence/unsafety.rs +++ b/src/librustc_typeck/coherence/unsafety.rs @@ -35,7 +35,7 @@ impl UnsafetyChecker<'tcx> { item.span, E0199, "implementing the trait `{}` is not unsafe", - trait_ref); + trait_ref.print_only_trait_path()); } (Unsafety::Unsafe, _, Unsafety::Normal, hir::ImplPolarity::Positive) => { @@ -43,7 +43,7 @@ impl UnsafetyChecker<'tcx> { item.span, E0200, "the trait `{}` requires an `unsafe impl` declaration", - trait_ref); + trait_ref.print_only_trait_path()); } (Unsafety::Normal, Some(attr_name), Unsafety::Normal, diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 612f3c69871d7..7d1f89079f808 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -343,14 +343,14 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt registry: rustc_driver::diagnostics_registry(), }; - interface::run_compiler_in_existing_thread_pool(config, |compiler| { + interface::run_compiler_in_existing_thread_pool(config, |compiler| compiler.enter(|queries| { let sess = compiler.session(); // We need to hold on to the complete resolver, so we cause everything to be // cloned for the analysis passes to use. Suboptimal, but necessary in the // current architecture. let resolver = { - let parts = abort_on_err(compiler.expansion(), sess).peek(); + let parts = abort_on_err(queries.expansion(), sess).peek(); let resolver = parts.1.borrow(); // Before we actually clone it, let's force all the extern'd crates to @@ -358,10 +358,11 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt // intra-doc-links resolver.borrow_mut().access(|resolver| { for extern_name in &extern_names { - resolver.resolve_str_path_error(DUMMY_SP, extern_name, TypeNS, CRATE_NODE_ID) - .unwrap_or_else( - |()| panic!("Unable to resolve external crate {}", extern_name) - ); + resolver.resolve_str_path_error( + DUMMY_SP, extern_name, TypeNS, CRATE_NODE_ID + ).unwrap_or_else( + |()| panic!("Unable to resolve external crate {}", extern_name) + ); } }); @@ -373,7 +374,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt sess.fatal("Compilation failed, aborting rustdoc"); } - let mut global_ctxt = abort_on_err(compiler.global_ctxt(), sess).take(); + let mut global_ctxt = abort_on_err(queries.global_ctxt(), sess).take(); global_ctxt.enter(|tcx| { tcx.analysis(LOCAL_CRATE).ok(); @@ -447,8 +448,8 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt }, sym::plugins => { report_deprecated_attr("plugins = \"...\"", diag); - eprintln!("WARNING: `#![doc(plugins = \"...\")]` no longer functions; \ - see CVE-2018-1000622"); + eprintln!("WARNING: `#![doc(plugins = \"...\")]` \ + no longer functions; see CVE-2018-1000622"); continue }, _ => continue, @@ -486,7 +487,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt (krate, ctxt.renderinfo.into_inner(), render_options) }) - }) + })) } /// `DefId` or parameter index (`ty::ParamTy.index`) of a synthetic type parameter diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 22f209b8bada1..d09eb0b2fc263 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -85,14 +85,14 @@ pub fn run(options: Options) -> i32 { let mut test_args = options.test_args.clone(); let display_warnings = options.display_warnings; - let tests = interface::run_compiler(config, |compiler| -> Result<_, ErrorReported> { - let lower_to_hir = compiler.lower_to_hir()?; + let tests = interface::run_compiler(config, |compiler| compiler.enter(|queries| { + let lower_to_hir = queries.lower_to_hir()?; - let mut opts = scrape_test_config(lower_to_hir.peek().0.borrow().krate()); + let mut opts = scrape_test_config(lower_to_hir.peek().0.krate()); opts.display_warnings |= options.display_warnings; let enable_per_target_ignores = options.enable_per_target_ignores; let mut collector = Collector::new( - compiler.crate_name()?.peek().to_string(), + queries.crate_name()?.peek().to_string(), options, false, opts, @@ -101,7 +101,8 @@ pub fn run(options: Options) -> i32 { enable_per_target_ignores, ); - let mut global_ctxt = compiler.global_ctxt()?.take(); + let mut global_ctxt = queries.global_ctxt()?.take(); + global_ctxt.enter(|tcx| { let krate = tcx.hir().krate(); let mut hir_collector = HirCollector { @@ -116,8 +117,9 @@ pub fn run(options: Options) -> i32 { }); }); - Ok(collector.tests) - }).expect("compiler aborted in rustdoc!"); + let ret : Result<_, ErrorReported> = Ok(collector.tests); + ret + })).expect("compiler aborted in rustdoc!"); test_args.insert(0, "rustdoctest".to_string()); diff --git a/src/libstd/panic.rs b/src/libstd/panic.rs index e36496d4c1c0d..cd024068d2d47 100644 --- a/src/libstd/panic.rs +++ b/src/libstd/panic.rs @@ -425,5 +425,5 @@ pub fn catch_unwind R + UnwindSafe, R>(f: F) -> Result { /// ``` #[stable(feature = "resume_unwind", since = "1.9.0")] pub fn resume_unwind(payload: Box) -> ! { - panicking::update_count_then_panic(payload) + panicking::rust_panic_without_hook(payload) } diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index 6819a4a04d737..c028ddcd676fc 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -20,6 +20,7 @@ use crate::sys_common::rwlock::RWLock; use crate::sys_common::{thread_info, util}; use crate::sys_common::backtrace::{self, RustBacktrace}; use crate::thread; +use crate::process; #[cfg(not(test))] use crate::io::set_panic; @@ -46,6 +47,8 @@ extern { vtable_ptr: *mut usize) -> u32; /// `payload` is actually a `*mut &mut dyn BoxMeUp` but that would cause FFI warnings. + /// It cannot be `Box` because the other end of this call does not depend + /// on liballoc, and thus cannot use `Box`. #[unwind(allowed)] fn __rust_start_panic(payload: usize) -> u32; } @@ -296,14 +299,6 @@ pub fn panicking() -> bool { update_panic_count(0) != 0 } -/// Entry point of panic from the libcore crate (`panic_impl` lang item). -#[cfg(not(test))] -#[panic_handler] -#[unwind(allowed)] -pub fn rust_begin_panic(info: &PanicInfo<'_>) -> ! { - continue_panic_fmt(&info) -} - /// The entry point for panicking with a formatted message. /// /// This is designed to reduce the amount of code required at the call @@ -324,13 +319,17 @@ pub fn begin_panic_fmt(msg: &fmt::Arguments<'_>, unsafe { intrinsics::abort() } } + // Just package everything into a `PanicInfo` and continue like libcore panics. let (file, line, col) = *file_line_col; let location = Location::internal_constructor(file, line, col); let info = PanicInfo::internal_constructor(Some(msg), &location); - continue_panic_fmt(&info) + begin_panic_handler(&info) } -fn continue_panic_fmt(info: &PanicInfo<'_>) -> ! { +/// Entry point of panics from the libcore crate (`panic_impl` lang item). +#[cfg_attr(not(test), panic_handler)] +#[unwind(allowed)] +pub fn begin_panic_handler(info: &PanicInfo<'_>) -> ! { struct PanicPayload<'a> { inner: &'a fmt::Arguments<'a>, string: Option, @@ -345,6 +344,7 @@ fn continue_panic_fmt(info: &PanicInfo<'_>) -> ! { use crate::fmt::Write; let inner = self.inner; + // Lazily, the first time this gets called, run the actual string formatting. self.string.get_or_insert_with(|| { let mut s = String::new(); drop(s.write_fmt(*inner)); @@ -354,7 +354,7 @@ fn continue_panic_fmt(info: &PanicInfo<'_>) -> ! { } unsafe impl<'a> BoxMeUp for PanicPayload<'a> { - fn box_me_up(&mut self) -> *mut (dyn Any + Send) { + fn take_box(&mut self) -> *mut (dyn Any + Send) { let contents = mem::take(self.fill()); Box::into_raw(Box::new(contents)) } @@ -378,7 +378,9 @@ fn continue_panic_fmt(info: &PanicInfo<'_>) -> ! { &file_line_col); } -/// This is the entry point of panicking for panic!() and assert!(). +/// This is the entry point of panicking for the non-format-string variants of +/// panic!() and assert!(). In particular, this is the only entry point that supports +/// arbitrary payloads, not just format strings. #[unstable(feature = "libstd_sys_internals", reason = "used by the panic! macro", issue = "0")] @@ -412,10 +414,10 @@ pub fn begin_panic(msg: M, file_line_col: &(&'static str, u32, u3 } unsafe impl BoxMeUp for PanicPayload { - fn box_me_up(&mut self) -> *mut (dyn Any + Send) { + fn take_box(&mut self) -> *mut (dyn Any + Send) { let data = match self.inner.take() { Some(a) => Box::new(a) as Box, - None => Box::new(()), + None => process::abort(), }; Box::into_raw(data) } @@ -423,7 +425,7 @@ pub fn begin_panic(msg: M, file_line_col: &(&'static str, u32, u3 fn get(&mut self) -> &(dyn Any + Send) { match self.inner { Some(ref a) => a, - None => &(), + None => process::abort(), } } } @@ -457,9 +459,12 @@ fn rust_panic_with_hook(payload: &mut dyn BoxMeUp, let mut info = PanicInfo::internal_constructor(message, &location); HOOK_LOCK.read(); match HOOK { - // Some platforms know that printing to stderr won't ever actually + // Some platforms (like wasm) know that printing to stderr won't ever actually // print anything, and if that's the case we can skip the default - // hook. + // hook. Since string formatting happens lazily when calling `payload` + // methods, this means we avoid formatting the string at all! + // (The panic runtime might still call `payload.take_box()` though and trigger + // formatting.) Hook::Default if panic_output().is_none() => {} Hook::Default => { info.set_payload(payload.get()); @@ -486,14 +491,15 @@ fn rust_panic_with_hook(payload: &mut dyn BoxMeUp, rust_panic(payload) } -/// Shim around rust_panic. Called by resume_unwind. -pub fn update_count_then_panic(msg: Box) -> ! { +/// This is the entry point for `resume_unwind`. +/// It just forwards the payload to the panic runtime. +pub fn rust_panic_without_hook(payload: Box) -> ! { update_panic_count(1); struct RewrapBox(Box); unsafe impl BoxMeUp for RewrapBox { - fn box_me_up(&mut self) -> *mut (dyn Any + Send) { + fn take_box(&mut self) -> *mut (dyn Any + Send) { Box::into_raw(mem::replace(&mut self.0, Box::new(()))) } @@ -502,7 +508,7 @@ pub fn update_count_then_panic(msg: Box) -> ! { } } - rust_panic(&mut RewrapBox(msg)) + rust_panic(&mut RewrapBox(payload)) } /// An unmangled function (through `rustc_std_internal_symbol`) on which to slap diff --git a/src/test/run-make-fulldeps/issue-19371/foo.rs b/src/test/run-make-fulldeps/issue-19371/foo.rs index f9ecff2abaa83..62a66aefd2deb 100644 --- a/src/test/run-make-fulldeps/issue-19371/foo.rs +++ b/src/test/run-make-fulldeps/issue-19371/foo.rs @@ -66,6 +66,11 @@ fn compile(code: String, output: PathBuf, sysroot: PathBuf) { interface::run_compiler(config, |compiler| { // This runs all the passes prior to linking, too. - compiler.link().ok(); + let linker = compiler.enter(|queries| { + queries.linker() + }); + if let Ok(linker) = linker { + linker.link(); + } }); } diff --git a/src/test/ui/async-await/issues/issue-66695-static-refs.rs b/src/test/ui/async-await/issues/issue-66695-static-refs.rs new file mode 100644 index 0000000000000..f0609713b4ddc --- /dev/null +++ b/src/test/ui/async-await/issues/issue-66695-static-refs.rs @@ -0,0 +1,24 @@ +// build-pass +// edition:2018 + +static A: [i32; 5] = [1, 2, 3, 4, 5]; + +async fn fun() { + let u = A[async { 1 }.await]; + match A { + i if async { true }.await => (), + _ => (), + } +} + +fn main() { + async { + let u = A[async { 1 }.await]; + }; + async { + match A { + i if async { true }.await => (), + _ => (), + } + }; +} diff --git a/src/test/ui/generator/static-reference-across-yield.rs b/src/test/ui/generator/static-reference-across-yield.rs new file mode 100644 index 0000000000000..23b11593bb5d6 --- /dev/null +++ b/src/test/ui/generator/static-reference-across-yield.rs @@ -0,0 +1,16 @@ +// build-pass +#![feature(generators)] + +static A: [i32; 5] = [1, 2, 3, 4, 5]; + +fn main() { + static || { + let u = A[{yield; 1}]; + }; + static || { + match A { + i if { yield; true } => (), + _ => (), + } + }; +}