From 4dd47d3b78a2b6f45dd382ac58fb182e40293ca3 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sun, 19 Apr 2020 18:17:31 +0100 Subject: [PATCH 1/6] Fix ICE for broken or-pattern in async fn --- src/librustc_mir_build/build/block.rs | 2 +- src/librustc_mir_build/build/matches/mod.rs | 59 ++++++++++++++----- .../build/matches/simplify.rs | 2 +- src/librustc_mir_build/hair/pattern/mod.rs | 7 ++- .../mismatched-bindings-async-fn.rs | 16 +++++ .../mismatched-bindings-async-fn.stderr | 35 +++++++++++ 6 files changed, 102 insertions(+), 19 deletions(-) create mode 100644 src/test/ui/or-patterns/mismatched-bindings-async-fn.rs create mode 100644 src/test/ui/or-patterns/mismatched-bindings-async-fn.stderr diff --git a/src/librustc_mir_build/build/block.rs b/src/librustc_mir_build/build/block.rs index 3f94fb8289031..fd69da8e24bfc 100644 --- a/src/librustc_mir_build/build/block.rs +++ b/src/librustc_mir_build/build/block.rs @@ -145,7 +145,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { })); debug!("ast_block_stmts: pattern={:?}", pattern); - this.visit_bindings( + this.visit_primary_bindings( &pattern, UserTypeProjections::none(), &mut |this, _, _, _, node, span, _, _| { diff --git a/src/librustc_mir_build/build/matches/mod.rs b/src/librustc_mir_build/build/matches/mod.rs index 10ffc81f179d1..715122e314c97 100644 --- a/src/librustc_mir_build/build/matches/mod.rs +++ b/src/librustc_mir_build/build/matches/mod.rs @@ -511,7 +511,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { opt_match_place: Option<(Option<&Place<'tcx>>, Span)>, ) -> Option { debug!("declare_bindings: pattern={:?}", pattern); - self.visit_bindings( + self.visit_primary_bindings( &pattern, UserTypeProjections::none(), &mut |this, mutability, name, mode, var, span, ty, user_ty| { @@ -563,7 +563,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.schedule_drop(span, region_scope, local_id, DropKind::Value); } - pub(super) fn visit_bindings( + /// Visit all of the primary bindings in a patterns, that is, visit the + /// leftmost occurrence of each variable bound in a pattern. A variable + /// will occur more than once in an or-pattern. + pub(super) fn visit_primary_bindings( &mut self, pattern: &Pat<'tcx>, pattern_user_ty: UserTypeProjections, @@ -578,12 +581,26 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { UserTypeProjections, ), ) { - debug!("visit_bindings: pattern={:?} pattern_user_ty={:?}", pattern, pattern_user_ty); + debug!( + "visit_primary_bindings: pattern={:?} pattern_user_ty={:?}", + pattern, pattern_user_ty + ); match *pattern.kind { - PatKind::Binding { mutability, name, mode, var, ty, ref subpattern, .. } => { - f(self, mutability, name, mode, var, pattern.span, ty, pattern_user_ty.clone()); + PatKind::Binding { + mutability, + name, + mode, + var, + ty, + ref subpattern, + is_primary, + .. + } => { + if is_primary { + f(self, mutability, name, mode, var, pattern.span, ty, pattern_user_ty.clone()); + } if let Some(subpattern) = subpattern.as_ref() { - self.visit_bindings(subpattern, pattern_user_ty, f); + self.visit_primary_bindings(subpattern, pattern_user_ty, f); } } @@ -592,20 +609,24 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let from = u32::try_from(prefix.len()).unwrap(); let to = u32::try_from(suffix.len()).unwrap(); for subpattern in prefix { - self.visit_bindings(subpattern, pattern_user_ty.clone().index(), f); + self.visit_primary_bindings(subpattern, pattern_user_ty.clone().index(), f); } for subpattern in slice { - self.visit_bindings(subpattern, pattern_user_ty.clone().subslice(from, to), f); + self.visit_primary_bindings( + subpattern, + pattern_user_ty.clone().subslice(from, to), + f, + ); } for subpattern in suffix { - self.visit_bindings(subpattern, pattern_user_ty.clone().index(), f); + self.visit_primary_bindings(subpattern, pattern_user_ty.clone().index(), f); } } PatKind::Constant { .. } | PatKind::Range { .. } | PatKind::Wild => {} PatKind::Deref { ref subpattern } => { - self.visit_bindings(subpattern, pattern_user_ty.deref(), f); + self.visit_primary_bindings(subpattern, pattern_user_ty.deref(), f); } PatKind::AscribeUserType { @@ -630,14 +651,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { projs: Vec::new(), }; let subpattern_user_ty = pattern_user_ty.push_projection(&projection, user_ty_span); - self.visit_bindings(subpattern, subpattern_user_ty, f) + self.visit_primary_bindings(subpattern, subpattern_user_ty, f) } PatKind::Leaf { ref subpatterns } => { for subpattern in subpatterns { let subpattern_user_ty = pattern_user_ty.clone().leaf(subpattern.field); - debug!("visit_bindings: subpattern_user_ty={:?}", subpattern_user_ty); - self.visit_bindings(&subpattern.pattern, subpattern_user_ty, f); + debug!("visit_primary_bindings: subpattern_user_ty={:?}", subpattern_user_ty); + self.visit_primary_bindings(&subpattern.pattern, subpattern_user_ty, f); } } @@ -645,11 +666,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { for subpattern in subpatterns { let subpattern_user_ty = pattern_user_ty.clone().variant(adt_def, variant_index, subpattern.field); - self.visit_bindings(&subpattern.pattern, subpattern_user_ty, f); + self.visit_primary_bindings(&subpattern.pattern, subpattern_user_ty, f); } } PatKind::Or { ref pats } => { - self.visit_bindings(&pats[0], pattern_user_ty, f); + // In cases where we recover from errors the primary bindings + // may not all be in the leftmost subpattern. For example in + // `let (x | y) = ...`, the primary binding of `y` occurs in + // the right subpattern + for subpattern in pats { + self.visit_primary_bindings(subpattern, pattern_user_ty.clone(), f); + } } } } @@ -1953,7 +1980,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { is_block_tail: None, local_info: LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm { binding_mode, - // hypothetically, `visit_bindings` could try to unzip + // hypothetically, `visit_primary_bindings` could try to unzip // an outermost hir::Ty as we descend, matching up // idents in pat; but complex w/ unclear UI payoff. // Instead, just abandon providing diagnostic info. diff --git a/src/librustc_mir_build/build/matches/simplify.rs b/src/librustc_mir_build/build/matches/simplify.rs index d74d8b5c7f318..09543cd1ce4e6 100644 --- a/src/librustc_mir_build/build/matches/simplify.rs +++ b/src/librustc_mir_build/build/matches/simplify.rs @@ -129,7 +129,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Ok(()) } - PatKind::Binding { name, mutability, mode, var, ty, ref subpattern } => { + PatKind::Binding { name, mutability, mode, var, ty, ref subpattern, is_primary: _ } => { candidate.bindings.push(Binding { name, mutability, diff --git a/src/librustc_mir_build/hair/pattern/mod.rs b/src/librustc_mir_build/hair/pattern/mod.rs index 2b6d8e920f5ed..33393ffe83fcb 100644 --- a/src/librustc_mir_build/hair/pattern/mod.rs +++ b/src/librustc_mir_build/hair/pattern/mod.rs @@ -133,6 +133,9 @@ crate enum PatKind<'tcx> { var: hir::HirId, ty: Ty<'tcx>, subpattern: Option>, + /// Is this the leftmost occurance of the binding, i.e., is `var` the + /// `HirId` of this pattern? + is_primary: bool, }, /// `Foo(...)` or `Foo{...}` or `Foo`, where `Foo` is a variant name from an ADT with @@ -601,6 +604,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { var: id, ty: var_ty, subpattern: self.lower_opt_pattern(sub), + is_primary: id == pat.hir_id, } } @@ -964,7 +968,7 @@ impl<'tcx> PatternFoldable<'tcx> for PatKind<'tcx> { user_ty_span, }, }, - PatKind::Binding { mutability, name, mode, var, ty, ref subpattern } => { + PatKind::Binding { mutability, name, mode, var, ty, ref subpattern, is_primary } => { PatKind::Binding { mutability: mutability.fold_with(folder), name: name.fold_with(folder), @@ -972,6 +976,7 @@ impl<'tcx> PatternFoldable<'tcx> for PatKind<'tcx> { var: var.fold_with(folder), ty: ty.fold_with(folder), subpattern: subpattern.fold_with(folder), + is_primary, } } PatKind::Variant { adt_def, substs, variant_index, ref subpatterns } => { diff --git a/src/test/ui/or-patterns/mismatched-bindings-async-fn.rs b/src/test/ui/or-patterns/mismatched-bindings-async-fn.rs new file mode 100644 index 0000000000000..5c5c68f81d1f2 --- /dev/null +++ b/src/test/ui/or-patterns/mismatched-bindings-async-fn.rs @@ -0,0 +1,16 @@ +// Regression test for #71297 +// edition:2018 + +#![feature(or_patterns)] + +async fn a((x | s): String) {} +//~^ ERROR variable `x` is not bound in all patterns +//~| ERROR variable `s` is not bound in all patterns + +async fn b() { + let x | s = String::new(); + //~^ ERROR variable `x` is not bound in all patterns + //~| ERROR variable `s` is not bound in all patterns +} + +fn main() {} diff --git a/src/test/ui/or-patterns/mismatched-bindings-async-fn.stderr b/src/test/ui/or-patterns/mismatched-bindings-async-fn.stderr new file mode 100644 index 0000000000000..b9c742664110e --- /dev/null +++ b/src/test/ui/or-patterns/mismatched-bindings-async-fn.stderr @@ -0,0 +1,35 @@ +error[E0408]: variable `x` is not bound in all patterns + --> $DIR/mismatched-bindings-async-fn.rs:6:17 + | +LL | async fn a((x | s): String) {} + | - ^ pattern doesn't bind `x` + | | + | variable not in all patterns + +error[E0408]: variable `s` is not bound in all patterns + --> $DIR/mismatched-bindings-async-fn.rs:6:13 + | +LL | async fn a((x | s): String) {} + | ^ - variable not in all patterns + | | + | pattern doesn't bind `s` + +error[E0408]: variable `x` is not bound in all patterns + --> $DIR/mismatched-bindings-async-fn.rs:11:13 + | +LL | let x | s = String::new(); + | - ^ pattern doesn't bind `x` + | | + | variable not in all patterns + +error[E0408]: variable `s` is not bound in all patterns + --> $DIR/mismatched-bindings-async-fn.rs:11:9 + | +LL | let x | s = String::new(); + | ^ - variable not in all patterns + | | + | pattern doesn't bind `s` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0408`. From 33b6631d9b2c79c548a9abdaf585a230b5f14ad9 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 1 May 2020 23:32:00 +0300 Subject: [PATCH 2/6] Enable `cfg` predicate for `target_feature = "crt-static"` only if the target supports it --- src/librustc_interface/util.rs | 2 +- src/librustc_session/session.rs | 11 +++-------- src/test/ui/crt-static-on-works.rs | 7 ++----- 3 files changed, 6 insertions(+), 14 deletions(-) diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs index c5a4d28d151b3..64114fbd1c489 100644 --- a/src/librustc_interface/util.rs +++ b/src/librustc_interface/util.rs @@ -49,7 +49,7 @@ pub fn add_configuration( cfg.extend(codegen_backend.target_features(sess).into_iter().map(|feat| (tf, Some(feat)))); - if sess.crt_static_feature(None) { + if sess.crt_static(None) { cfg.insert((tf, Some(Symbol::intern("crt-static")))); } } diff --git a/src/librustc_session/session.rs b/src/librustc_session/session.rs index 69e1b46de4df7..f85be218bc218 100644 --- a/src/librustc_session/session.rs +++ b/src/librustc_session/session.rs @@ -553,16 +553,11 @@ impl Session { /// Check whether this compile session and crate type use static crt. pub fn crt_static(&self, crate_type: Option) -> bool { - // If the target does not opt in to crt-static support, use its default. - if self.target.target.options.crt_static_respected { - self.crt_static_feature(crate_type) - } else { - self.target.target.options.crt_static_default + if !self.target.target.options.crt_static_respected { + // If the target does not opt in to crt-static support, use its default. + return self.target.target.options.crt_static_default; } - } - /// Check whether this compile session and crate type use `crt-static` feature. - pub fn crt_static_feature(&self, crate_type: Option) -> bool { let requested_features = self.opts.cg.target_feature.split(','); let found_negative = requested_features.clone().any(|r| r == "-crt-static"); let found_positive = requested_features.clone().any(|r| r == "+crt-static"); diff --git a/src/test/ui/crt-static-on-works.rs b/src/test/ui/crt-static-on-works.rs index 21407b1b9118c..f89d1edd6586a 100644 --- a/src/test/ui/crt-static-on-works.rs +++ b/src/test/ui/crt-static-on-works.rs @@ -1,9 +1,6 @@ // run-pass - -#![allow(stable_features)] -// compile-flags:-C target-feature=+crt-static -Z unstable-options - -#![feature(cfg_target_feature)] +// compile-flags:-C target-feature=+crt-static +// only-msvc #[cfg(target_feature = "crt-static")] fn main() {} From abbc7365a726269e13b7ee2864bb6086dfc41d69 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 8 May 2020 15:19:14 +0200 Subject: [PATCH 3/6] Add emoji for deprecated messages --- src/librustdoc/html/render.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 666e59b9a045e..82f91e232df3b 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -2281,7 +2281,10 @@ fn short_stability(item: &clean::Item, cx: &Context) -> Vec { ); message.push_str(&format!(": {}", html.to_string())); } - stability.push(format!("
{}
", message)); + stability.push(format!( + "
👎 {}
", + message, + )); } if let Some(stab) = item.stability.as_ref().filter(|stab| stab.level == stability::Unstable) { From 9d8310856b3a42aa99d6591244a6679284011dc9 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 8 May 2020 15:27:08 +0200 Subject: [PATCH 4/6] Add test for deprecated emoji --- src/test/rustdoc/issue-32374.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/rustdoc/issue-32374.rs b/src/test/rustdoc/issue-32374.rs index 7babfaf6060f4..11caa34d4b114 100644 --- a/src/test/rustdoc/issue-32374.rs +++ b/src/test/rustdoc/issue-32374.rs @@ -10,7 +10,7 @@ // @matches issue_32374/index.html '//*[@class="docblock-short"]/text()' 'Docs' // @has issue_32374/struct.T.html '//*[@class="stab deprecated"]' \ -// 'Deprecated since 1.0.0: text' +// '👎 Deprecated since 1.0.0: text' // @has - 'test #32374' // @matches issue_32374/struct.T.html '//*[@class="stab unstable"]' \ // '🔬 This is a nightly-only experimental API. \(test\s#32374\)$' @@ -20,7 +20,7 @@ pub struct T; // @has issue_32374/struct.U.html '//*[@class="stab deprecated"]' \ -// 'Deprecated since 1.0.0: deprecated' +// '👎 Deprecated since 1.0.0: deprecated' // @has issue_32374/struct.U.html '//*[@class="stab unstable"]' \ // '🔬 This is a nightly-only experimental API. (test #32374)' // @has issue_32374/struct.U.html '//details' \ From 882b50854cfdac67bd743ec9fd02464eca6edf15 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 8 May 2020 09:27:59 -0700 Subject: [PATCH 5/6] Fix disagreeement about CGU reuse and LTO This commit fixes an issue where the codegen backend's selection of LTO disagreed with what the codegen later thought was being done. Discovered in #72006 we have a longstanding issue where if `-Clinker-plugin-lto` in optimized mode is compiled incrementally it will always panic on the second compilation. The underlying issue turned out to be that the production of the original artifact determined that LTO should not be done (because it's being postponed to the linker) but the CGU reuse selection thought that LTO was done so it was trying to load pre-LTO artifacts which were never generated. The fix here is to ensure that the logic when generating code which determines what kind of LTO is being done is shared amongst the CGU reuse decision and the backend actually doing LTO. This means that they'll both be in agreement about whether the previous compilation did indeed produce incremental pre-LTO artifacts. Closes #72006 --- src/librustc_codegen_ssa/back/write.rs | 69 +++++++++++++++----------- src/librustc_codegen_ssa/base.rs | 20 ++++++-- src/test/incremental/lto-in-linker.rs | 8 +++ src/test/incremental/rlib-lto.rs | 8 +++ 4 files changed, 70 insertions(+), 35 deletions(-) create mode 100644 src/test/incremental/lto-in-linker.rs create mode 100644 src/test/incremental/rlib-lto.rs diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs index 5c3444eff0a11..e5bd18ed680de 100644 --- a/src/librustc_codegen_ssa/back/write.rs +++ b/src/librustc_codegen_ssa/back/write.rs @@ -715,38 +715,34 @@ fn execute_work_item( } // Actual LTO type we end up choosing based on multiple factors. -enum ComputedLtoType { +pub enum ComputedLtoType { No, Thin, Fat, } -fn execute_optimize_work_item( - cgcx: &CodegenContext, - module: ModuleCodegen, - module_config: &ModuleConfig, -) -> Result, FatalError> { - let diag_handler = cgcx.create_diag_handler(); - - unsafe { - B::optimize(cgcx, &diag_handler, &module, module_config)?; +pub fn compute_per_cgu_lto_type( + sess_lto: &Lto, + opts: &config::Options, + sess_crate_types: &[CrateType], + module_kind: ModuleKind, +) -> ComputedLtoType { + // Metadata modules never participate in LTO regardless of the lto + // settings. + if module_kind == ModuleKind::Metadata { + return ComputedLtoType::No; } - // After we've done the initial round of optimizations we need to - // decide whether to synchronously codegen this module or ship it - // back to the coordinator thread for further LTO processing (which - // has to wait for all the initial modules to be optimized). - // If the linker does LTO, we don't have to do it. Note that we // keep doing full LTO, if it is requested, as not to break the // assumption that the output will be a single module. - let linker_does_lto = cgcx.opts.cg.linker_plugin_lto.enabled(); + let linker_does_lto = opts.cg.linker_plugin_lto.enabled(); // When we're automatically doing ThinLTO for multi-codegen-unit // builds we don't actually want to LTO the allocator modules if // it shows up. This is due to various linker shenanigans that // we'll encounter later. - let is_allocator = module.kind == ModuleKind::Allocator; + let is_allocator = module_kind == ModuleKind::Allocator; // We ignore a request for full crate grath LTO if the cate type // is only an rlib, as there is no full crate graph to process, @@ -756,20 +752,33 @@ fn execute_optimize_work_item( // require LTO so the request for LTO is always unconditionally // passed down to the backend, but we don't actually want to do // anything about it yet until we've got a final product. - let is_rlib = cgcx.crate_types.len() == 1 && cgcx.crate_types[0] == CrateType::Rlib; + let is_rlib = sess_crate_types.len() == 1 && sess_crate_types[0] == CrateType::Rlib; - // Metadata modules never participate in LTO regardless of the lto - // settings. - let lto_type = if module.kind == ModuleKind::Metadata { - ComputedLtoType::No - } else { - match cgcx.lto { - Lto::ThinLocal if !linker_does_lto && !is_allocator => ComputedLtoType::Thin, - Lto::Thin if !linker_does_lto && !is_rlib => ComputedLtoType::Thin, - Lto::Fat if !is_rlib => ComputedLtoType::Fat, - _ => ComputedLtoType::No, - } - }; + match sess_lto { + Lto::ThinLocal if !linker_does_lto && !is_allocator => ComputedLtoType::Thin, + Lto::Thin if !linker_does_lto && !is_rlib => ComputedLtoType::Thin, + Lto::Fat if !is_rlib => ComputedLtoType::Fat, + _ => ComputedLtoType::No, + } +} + +fn execute_optimize_work_item( + cgcx: &CodegenContext, + module: ModuleCodegen, + module_config: &ModuleConfig, +) -> Result, FatalError> { + let diag_handler = cgcx.create_diag_handler(); + + unsafe { + B::optimize(cgcx, &diag_handler, &module, module_config)?; + } + + // After we've done the initial round of optimizations we need to + // decide whether to synchronously codegen this module or ship it + // back to the coordinator thread for further LTO processing (which + // has to wait for all the initial modules to be optimized). + + let lto_type = compute_per_cgu_lto_type(&cgcx.lto, &cgcx.opts, &cgcx.crate_types, module.kind); // If we're doing some form of incremental LTO then we need to be sure to // save our module to disk first. diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs index c5b95905ea012..29398db6ff8a9 100644 --- a/src/librustc_codegen_ssa/base.rs +++ b/src/librustc_codegen_ssa/base.rs @@ -14,8 +14,8 @@ //! int)` and `rec(x=int, y=int, z=int)` will have the same `llvm::Type`. use crate::back::write::{ - start_async_codegen, submit_codegened_module_to_llvm, submit_post_lto_module_to_llvm, - submit_pre_lto_module_to_llvm, OngoingCodegen, + compute_per_cgu_lto_type, start_async_codegen, submit_codegened_module_to_llvm, + submit_post_lto_module_to_llvm, submit_pre_lto_module_to_llvm, ComputedLtoType, OngoingCodegen, }; use crate::common::{IntPredicate, RealPredicate, TypeKind}; use crate::meth; @@ -43,7 +43,7 @@ use rustc_middle::ty::layout::{FAT_PTR_ADDR, FAT_PTR_EXTRA}; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; use rustc_session::cgu_reuse_tracker::CguReuse; -use rustc_session::config::{self, EntryFnType, Lto}; +use rustc_session::config::{self, EntryFnType}; use rustc_session::Session; use rustc_span::Span; use rustc_symbol_mangling::test as symbol_names_test; @@ -941,8 +941,18 @@ fn determine_cgu_reuse<'tcx>(tcx: TyCtxt<'tcx>, cgu: &CodegenUnit<'tcx>) -> CguR ); if tcx.dep_graph.try_mark_green(tcx, &dep_node).is_some() { - // We can re-use either the pre- or the post-thinlto state - if tcx.sess.lto() != Lto::No { CguReuse::PreLto } else { CguReuse::PostLto } + // We can re-use either the pre- or the post-thinlto state. If no LTO is + // being performed then we can use post-LTO artifacts, otherwise we must + // reuse pre-LTO artifacts + match compute_per_cgu_lto_type( + &tcx.sess.lto(), + &tcx.sess.opts, + &tcx.sess.crate_types.borrow(), + ModuleKind::Regular, + ) { + ComputedLtoType::No => CguReuse::PostLto, + _ => CguReuse::PreLto, + } } else { CguReuse::No } diff --git a/src/test/incremental/lto-in-linker.rs b/src/test/incremental/lto-in-linker.rs new file mode 100644 index 0000000000000..6d21f267ace05 --- /dev/null +++ b/src/test/incremental/lto-in-linker.rs @@ -0,0 +1,8 @@ +// revisions:cfail1 cfail2 +// compile-flags: -Z query-dep-graph --crate-type rlib -C linker-plugin-lto -O +// build-pass + +#![feature(rustc_attrs)] +#![rustc_partition_reused(module = "lto_in_linker", cfg = "cfail2")] + +pub fn foo() {} diff --git a/src/test/incremental/rlib-lto.rs b/src/test/incremental/rlib-lto.rs new file mode 100644 index 0000000000000..752fee5a0d5b6 --- /dev/null +++ b/src/test/incremental/rlib-lto.rs @@ -0,0 +1,8 @@ +// revisions:cfail1 cfail2 +// compile-flags: -Z query-dep-graph --crate-type rlib -C lto +// build-pass + +#![feature(rustc_attrs)] +#![rustc_partition_reused(module = "rlib_lto", cfg = "cfail2")] + +pub fn foo() {} From e0c0c3b96f96bcb95153c8813c0969c780662dc9 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 9 May 2020 13:48:11 +0200 Subject: [PATCH 6/6] Add missing backtick in E0569 explanation --- src/librustc_error_codes/error_codes/E0569.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_error_codes/error_codes/E0569.md b/src/librustc_error_codes/error_codes/E0569.md index 4cba0cf9c96ba..2ca2b57ecace5 100644 --- a/src/librustc_error_codes/error_codes/E0569.md +++ b/src/librustc_error_codes/error_codes/E0569.md @@ -1,5 +1,5 @@ If an impl has a generic parameter with the `#[may_dangle]` attribute, then -that impl must be declared as an `unsafe impl. +that impl must be declared as an `unsafe impl`. Erroneous code example: