about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-01-13 04:29:45 +0000
committerbors <bors@rust-lang.org>2021-01-13 04:29:45 +0000
commitfc93e4719c2ced744d75f0c281bb7ba29844bedd (patch)
tree8f137593f07f9ad050e78a3d37ce120357870e78 /compiler
parent150d1fee04856ff158e34e8d687a7fe59e97ef33 (diff)
parent5b90fe1c3094050eecbb7be7440b398e98d0caa2 (diff)
downloadrust-fc93e4719c2ced744d75f0c281bb7ba29844bedd.tar.gz
rust-fc93e4719c2ced744d75f0c281bb7ba29844bedd.zip
Auto merge of #80960 - Dylan-DPC:rollup-89tri8x, r=Dylan-DPC
Rollup of 10 pull requests

Successful merges:

 - #78901 (diagnostics: Note capturing closures can't be coerced to fns)
 - #79588 (Provide more information for HRTB lifetime errors involving closures)
 - #80232 (Remove redundant def_id lookups)
 - #80662 (Added support for i386-unknown-linux-gnu and i486-unknown-linux-gnu)
 - #80736 (use Once instead of Mutex to manage capture resolution)
 - #80796 (Update to LLVM 11.0.1)
 - #80859 (Fix --pretty=expanded with --remap-path-prefix)
 - #80922 (Revert "Auto merge of #76896 - spastorino:codegen-inline-fns2)
 - #80924 (Fix rustdoc --test-builder argument parsing)
 - #80935 (Rename `rustc_middle::lint::LevelSource` to `LevelAndSource`)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_driver/src/pretty.rs11
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs12
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/note.rs64
-rw-r--r--compiler/rustc_lint/src/levels.rs6
-rw-r--r--compiler/rustc_middle/src/lint.rs14
-rw-r--r--compiler/rustc_middle/src/mir/mono.rs40
-rw-r--r--compiler/rustc_middle/src/ty/consts.rs3
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/expr.rs3
-rw-r--r--compiler/rustc_span/src/source_map.rs15
-rw-r--r--compiler/rustc_target/src/spec/i386_unknown_linux_gnu.rs8
-rw-r--r--compiler/rustc_target/src/spec/i486_unknown_linux_gnu.rs8
-rw-r--r--compiler/rustc_typeck/src/check/demand.rs1
-rw-r--r--compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs34
13 files changed, 171 insertions, 48 deletions
diff --git a/compiler/rustc_driver/src/pretty.rs b/compiler/rustc_driver/src/pretty.rs
index 305fa838afa..b7edc24bc4a 100644
--- a/compiler/rustc_driver/src/pretty.rs
+++ b/compiler/rustc_driver/src/pretty.rs
@@ -363,8 +363,15 @@ impl<'tcx> pprust_hir::PpAnn for TypedAnnotation<'tcx> {
 
 fn get_source(input: &Input, sess: &Session) -> (String, FileName) {
     let src_name = input.source_name();
-    let src =
-        String::clone(&sess.source_map().get_source_file(&src_name).unwrap().src.as_ref().unwrap());
+    let src = String::clone(
+        &sess
+            .source_map()
+            .get_source_file(&src_name)
+            .expect("get_source_file")
+            .src
+            .as_ref()
+            .expect("src"),
+    );
     (src, src_name)
 }
 
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 7b0a91986b3..5d56744805f 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -98,7 +98,7 @@ pub(super) fn note_and_explain_region(
         // uh oh, hope no user ever sees THIS
         ty::ReEmpty(ui) => (format!("the empty lifetime in universe {:?}", ui), None),
 
-        ty::RePlaceholder(_) => ("any other region".to_string(), None),
+        ty::RePlaceholder(_) => return,
 
         // FIXME(#13998) RePlaceholder should probably print like
         // ReFree rather than dumping Debug output on the user.
@@ -1675,6 +1675,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         self.check_and_note_conflicting_crates(diag, terr);
         self.tcx.note_and_explain_type_err(diag, terr, cause, span, body_owner_def_id.to_def_id());
 
+        if let Some(ValuePairs::PolyTraitRefs(exp_found)) = values {
+            if let ty::Closure(def_id, _) = exp_found.expected.skip_binder().self_ty().kind() {
+                if let Some(def_id) = def_id.as_local() {
+                    let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
+                    let span = self.tcx.hir().span(hir_id);
+                    diag.span_note(span, "this closure does not fulfill the lifetime requirements");
+                }
+            }
+        }
+
         // It reads better to have the error origin as the final
         // thing.
         self.note_error_origin(diag, cause, exp_found);
diff --git a/compiler/rustc_infer/src/infer/error_reporting/note.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs
index 7fb94332cad..c88869abc29 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/note.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs
@@ -1,6 +1,7 @@
 use crate::infer::error_reporting::{note_and_explain_region, ObligationCauseExt};
 use crate::infer::{self, InferCtxt, SubregionOrigin};
 use rustc_errors::{struct_span_err, DiagnosticBuilder};
+use rustc_middle::traits::ObligationCauseCode;
 use rustc_middle::ty::error::TypeError;
 use rustc_middle::ty::{self, Region};
 
@@ -107,14 +108,37 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
             infer::Subtype(box trace) => {
                 let terr = TypeError::RegionsDoesNotOutlive(sup, sub);
                 let mut err = self.report_and_explain_type_error(trace, &terr);
-                note_and_explain_region(self.tcx, &mut err, "", sup, "...");
-                note_and_explain_region(
-                    self.tcx,
-                    &mut err,
-                    "...does not necessarily outlive ",
-                    sub,
-                    "",
-                );
+                match (sub, sup) {
+                    (ty::RePlaceholder(_), ty::RePlaceholder(_)) => {}
+                    (ty::RePlaceholder(_), _) => {
+                        note_and_explain_region(
+                            self.tcx,
+                            &mut err,
+                            "",
+                            sup,
+                            " doesn't meet the lifetime requirements",
+                        );
+                    }
+                    (_, ty::RePlaceholder(_)) => {
+                        note_and_explain_region(
+                            self.tcx,
+                            &mut err,
+                            "the required lifetime does not necessarily outlive ",
+                            sub,
+                            "",
+                        );
+                    }
+                    _ => {
+                        note_and_explain_region(self.tcx, &mut err, "", sup, "...");
+                        note_and_explain_region(
+                            self.tcx,
+                            &mut err,
+                            "...does not necessarily outlive ",
+                            sub,
+                            "",
+                        );
+                    }
+                }
                 err
             }
             infer::Reborrow(span) => {
@@ -286,13 +310,31 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         sup: Region<'tcx>,
     ) -> DiagnosticBuilder<'tcx> {
         // I can't think how to do better than this right now. -nikomatsakis
+        debug!(?placeholder_origin, ?sub, ?sup, "report_placeholder_failure");
         match placeholder_origin {
+            infer::Subtype(box ref trace)
+                if matches!(
+                    &trace.cause.code.peel_derives(),
+                    ObligationCauseCode::BindingObligation(..)
+                ) =>
+            {
+                // Hack to get around the borrow checker because trace.cause has an `Rc`.
+                if let ObligationCauseCode::BindingObligation(_, span) =
+                    &trace.cause.code.peel_derives()
+                {
+                    let span = *span;
+                    let mut err = self.report_concrete_failure(placeholder_origin, sub, sup);
+                    err.span_note(span, "the lifetime requirement is introduced here");
+                    err
+                } else {
+                    unreachable!()
+                }
+            }
             infer::Subtype(box trace) => {
                 let terr = TypeError::RegionsPlaceholderMismatch;
-                self.report_and_explain_type_error(trace, &terr)
+                return self.report_and_explain_type_error(trace, &terr);
             }
-
-            _ => self.report_concrete_failure(placeholder_origin, sub, sup),
+            _ => return self.report_concrete_failure(placeholder_origin, sub, sup),
         }
     }
 }
diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs
index 5cece569903..37bdc878b16 100644
--- a/compiler/rustc_lint/src/levels.rs
+++ b/compiler/rustc_lint/src/levels.rs
@@ -10,7 +10,7 @@ use rustc_hir as hir;
 use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
 use rustc_hir::{intravisit, HirId};
 use rustc_middle::hir::map::Map;
-use rustc_middle::lint::LevelSource;
+use rustc_middle::lint::LevelAndSource;
 use rustc_middle::lint::LintDiagnosticBuilder;
 use rustc_middle::lint::{
     struct_lint_level, LintLevelMap, LintLevelSets, LintLevelSource, LintSet,
@@ -106,9 +106,9 @@ impl<'s> LintLevelsBuilder<'s> {
     /// diagnostic with no change to `specs`.
     fn insert_spec(
         &mut self,
-        specs: &mut FxHashMap<LintId, LevelSource>,
+        specs: &mut FxHashMap<LintId, LevelAndSource>,
         id: LintId,
-        (level, src): LevelSource,
+        (level, src): LevelAndSource,
     ) {
         // Setting to a non-forbid level is an error if the lint previously had
         // a forbid level. Note that this is not necessarily true even with a
diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs
index 64d850192f4..80c87dddd56 100644
--- a/compiler/rustc_middle/src/lint.rs
+++ b/compiler/rustc_middle/src/lint.rs
@@ -46,7 +46,7 @@ impl LintLevelSource {
 }
 
 /// A tuple of a lint level and its source.
-pub type LevelSource = (Level, LintLevelSource);
+pub type LevelAndSource = (Level, LintLevelSource);
 
 pub struct LintLevelSets {
     pub list: Vec<LintSet>,
@@ -57,11 +57,11 @@ pub enum LintSet {
     CommandLine {
         // -A,-W,-D flags, a `Symbol` for the flag itself and `Level` for which
         // flag.
-        specs: FxHashMap<LintId, LevelSource>,
+        specs: FxHashMap<LintId, LevelAndSource>,
     },
 
     Node {
-        specs: FxHashMap<LintId, LevelSource>,
+        specs: FxHashMap<LintId, LevelAndSource>,
         parent: u32,
     },
 }
@@ -75,9 +75,9 @@ impl LintLevelSets {
         &self,
         lint: &'static Lint,
         idx: u32,
-        aux: Option<&FxHashMap<LintId, LevelSource>>,
+        aux: Option<&FxHashMap<LintId, LevelAndSource>>,
         sess: &Session,
-    ) -> LevelSource {
+    ) -> LevelAndSource {
         let (level, mut src) = self.get_lint_id_level(LintId::of(lint), idx, aux);
 
         // If `level` is none then we actually assume the default level for this
@@ -113,7 +113,7 @@ impl LintLevelSets {
         &self,
         id: LintId,
         mut idx: u32,
-        aux: Option<&FxHashMap<LintId, LevelSource>>,
+        aux: Option<&FxHashMap<LintId, LevelAndSource>>,
     ) -> (Option<Level>, LintLevelSource) {
         if let Some(specs) = aux {
             if let Some(&(level, src)) = specs.get(&id) {
@@ -157,7 +157,7 @@ impl LintLevelMap {
         lint: &'static Lint,
         id: HirId,
         session: &Session,
-    ) -> Option<LevelSource> {
+    ) -> Option<LevelAndSource> {
         self.id_to_set.get(&id).map(|idx| self.sets.get_lint_level(lint, *idx, None, session))
     }
 }
diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs
index 698c2521596..f810f6a56a5 100644
--- a/compiler/rustc_middle/src/mir/mono.rs
+++ b/compiler/rustc_middle/src/mir/mono.rs
@@ -1,6 +1,7 @@
 use crate::dep_graph::{dep_constructor, DepNode, WorkProduct, WorkProductId};
 use crate::ich::{NodeIdHashingMode, StableHashingContext};
 use crate::ty::{subst::InternalSubsts, Instance, InstanceDef, SymbolName, TyCtxt};
+use rustc_attr::InlineAttr;
 use rustc_data_structures::base_n;
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::FxHashMap;
@@ -78,6 +79,14 @@ impl<'tcx> MonoItem<'tcx> {
     }
 
     pub fn instantiation_mode(&self, tcx: TyCtxt<'tcx>) -> InstantiationMode {
+        let generate_cgu_internal_copies = tcx
+            .sess
+            .opts
+            .debugging_opts
+            .inline_in_all_cgus
+            .unwrap_or_else(|| tcx.sess.opts.optimize != OptLevel::No)
+            && !tcx.sess.link_dead_code();
+
         match *self {
             MonoItem::Fn(ref instance) => {
                 let entry_def_id = tcx.entry_fn(LOCAL_CRATE).map(|(id, _)| id);
@@ -90,26 +99,21 @@ impl<'tcx> MonoItem<'tcx> {
                     return InstantiationMode::GloballyShared { may_conflict: false };
                 }
 
-                let generate_cgu_internal_copies = tcx
-                    .sess
-                    .opts
-                    .debugging_opts
-                    .inline_in_all_cgus
-                    .unwrap_or_else(|| tcx.sess.opts.optimize != OptLevel::No)
-                    && !tcx.sess.link_dead_code();
-
                 // At this point we don't have explicit linkage and we're an
-                // inlined function. If we should generate local copies for each CGU,
-                // then return `LocalCopy`, otherwise we'll just generate one copy
-                // and share it with all CGUs in this crate.
+                // inlined function. If we're inlining into all CGUs then we'll
+                // be creating a local copy per CGU.
                 if generate_cgu_internal_copies {
-                    InstantiationMode::LocalCopy
-                } else {
-                    // Finally, if we've reached this point, then we should optimize for
-                    // compilation speed. In that regard, we will ignore any `#[inline]`
-                    // annotations on the function and simply codegen it as usual. This could
-                    // conflict with upstream crates as it could be an exported symbol.
-                    InstantiationMode::GloballyShared { may_conflict: true }
+                    return InstantiationMode::LocalCopy;
+                }
+
+                // Finally, if this is `#[inline(always)]` we're sure to respect
+                // that with an inline copy per CGU, but otherwise we'll be
+                // creating one copy of this `#[inline]` function which may
+                // conflict with upstream crates as it could be an exported
+                // symbol.
+                match tcx.codegen_fn_attrs(instance.def_id()).inline {
+                    InlineAttr::Always => InstantiationMode::LocalCopy,
+                    _ => InstantiationMode::GloballyShared { may_conflict: true },
                 }
             }
             MonoItem::Static(..) | MonoItem::GlobalAsm(..) => {
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index 0af884a286d..041c040f0b7 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -92,8 +92,7 @@ impl<'tcx> Const<'tcx> {
                 let item_id = tcx.hir().get_parent_node(hir_id);
                 let item_def_id = tcx.hir().local_def_id(item_id);
                 let generics = tcx.generics_of(item_def_id.to_def_id());
-                let index =
-                    generics.param_def_id_to_index[&tcx.hir().local_def_id(hir_id).to_def_id()];
+                let index = generics.param_def_id_to_index[&def_id];
                 let name = tcx.hir().name(hir_id);
                 ty::ConstKind::Param(ty::ParamConst::new(index, name))
             }
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index 417f9bded09..625a0989ab3 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -813,8 +813,7 @@ fn convert_path_expr<'a, 'tcx>(
             let item_id = cx.tcx.hir().get_parent_node(hir_id);
             let item_def_id = cx.tcx.hir().local_def_id(item_id);
             let generics = cx.tcx.generics_of(item_def_id);
-            let local_def_id = cx.tcx.hir().local_def_id(hir_id);
-            let index = generics.param_def_id_to_index[&local_def_id.to_def_id()];
+            let index = generics.param_def_id_to_index[&def_id];
             let name = cx.tcx.hir().name(hir_id);
             let val = ty::ConstKind::Param(ty::ParamConst::new(index, name));
             ExprKind::Literal {
diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs
index 6635d44496c..a7b8c8ba1d4 100644
--- a/compiler/rustc_span/src/source_map.rs
+++ b/compiler/rustc_span/src/source_map.rs
@@ -872,8 +872,10 @@ impl SourceMap {
     }
 
     pub fn get_source_file(&self, filename: &FileName) -> Option<Lrc<SourceFile>> {
+        // Remap filename before lookup
+        let filename = self.path_mapping().map_filename_prefix(filename).0;
         for sf in self.files.borrow().source_files.iter() {
-            if *filename == sf.name {
+            if filename == sf.name {
                 return Some(sf.clone());
             }
         }
@@ -1041,4 +1043,15 @@ impl FilePathMapping {
 
         (path, false)
     }
+
+    fn map_filename_prefix(&self, file: &FileName) -> (FileName, bool) {
+        match file {
+            FileName::Real(realfile) => {
+                let path = realfile.local_path();
+                let (path, mapped) = self.map_prefix(path.to_path_buf());
+                (FileName::Real(RealFileName::Named(path)), mapped)
+            }
+            other => (other.clone(), false),
+        }
+    }
 }
diff --git a/compiler/rustc_target/src/spec/i386_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/i386_unknown_linux_gnu.rs
new file mode 100644
index 00000000000..f329b2d2c88
--- /dev/null
+++ b/compiler/rustc_target/src/spec/i386_unknown_linux_gnu.rs
@@ -0,0 +1,8 @@
+use crate::spec::Target;
+
+pub fn target() -> Target {
+    let mut base = super::i686_unknown_linux_gnu::target();
+    base.cpu = "i386".to_string();
+    base.llvm_target = "i386-unknown-linux-gnu".to_string();
+    base
+}
diff --git a/compiler/rustc_target/src/spec/i486_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/i486_unknown_linux_gnu.rs
new file mode 100644
index 00000000000..5d96a558cb7
--- /dev/null
+++ b/compiler/rustc_target/src/spec/i486_unknown_linux_gnu.rs
@@ -0,0 +1,8 @@
+use crate::spec::Target;
+
+pub fn target() -> Target {
+    let mut base = super::i686_unknown_linux_gnu::target();
+    base.cpu = "i486".to_string();
+    base.llvm_target = "i486-unknown-linux-gnu".to_string();
+    base
+}
diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs
index 2728e03171a..c22f0017446 100644
--- a/compiler/rustc_typeck/src/check/demand.rs
+++ b/compiler/rustc_typeck/src/check/demand.rs
@@ -32,6 +32,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         if self.suggest_calling_boxed_future_when_appropriate(err, expr, expected, expr_ty) {
             return;
         }
+        self.suggest_no_capture_closure(err, expected, expr_ty);
         self.suggest_boxing_when_appropriate(err, expr, expected, expr_ty);
         self.suggest_missing_parentheses(err, expr);
         self.note_need_for_fn_pointer(err, expected, expr_ty);
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
index 17dbf989d66..9fbf330fe02 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
@@ -2,7 +2,7 @@ use super::FnCtxt;
 use crate::astconv::AstConv;
 
 use rustc_ast::util::parser::ExprPrecedence;
-use rustc_span::{self, Span};
+use rustc_span::{self, MultiSpan, Span};
 
 use rustc_errors::{Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
@@ -287,6 +287,38 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
     }
 
+    /// When encountering a closure that captures variables, where a FnPtr is expected,
+    /// suggest a non-capturing closure
+    pub(in super::super) fn suggest_no_capture_closure(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        expected: Ty<'tcx>,
+        found: Ty<'tcx>,
+    ) {
+        if let (ty::FnPtr(_), ty::Closure(def_id, _)) = (expected.kind(), found.kind()) {
+            if let Some(upvars) = self.tcx.upvars_mentioned(*def_id) {
+                // Report upto four upvars being captured to reduce the amount error messages
+                // reported back to the user.
+                let spans_and_labels = upvars
+                    .iter()
+                    .take(4)
+                    .map(|(var_hir_id, upvar)| {
+                        let var_name = self.tcx.hir().name(*var_hir_id).to_string();
+                        let msg = format!("`{}` captured here", var_name);
+                        (upvar.span, msg)
+                    })
+                    .collect::<Vec<_>>();
+
+                let mut multi_span: MultiSpan =
+                    spans_and_labels.iter().map(|(sp, _)| *sp).collect::<Vec<_>>().into();
+                for (sp, label) in spans_and_labels {
+                    multi_span.push_span_label(sp, label);
+                }
+                err.span_note(multi_span, "closures can only be coerced to `fn` types if they do not capture any variables");
+            }
+        }
+    }
+
     /// When encountering an `impl Future` where `BoxFuture` is expected, suggest `Box::pin`.
     pub(in super::super) fn suggest_calling_boxed_future_when_appropriate(
         &self,