diff options
| author | bors <bors@rust-lang.org> | 2021-01-13 04:29:45 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2021-01-13 04:29:45 +0000 |
| commit | fc93e4719c2ced744d75f0c281bb7ba29844bedd (patch) | |
| tree | 8f137593f07f9ad050e78a3d37ce120357870e78 /compiler | |
| parent | 150d1fee04856ff158e34e8d687a7fe59e97ef33 (diff) | |
| parent | 5b90fe1c3094050eecbb7be7440b398e98d0caa2 (diff) | |
| download | rust-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.rs | 11 | ||||
| -rw-r--r-- | compiler/rustc_infer/src/infer/error_reporting/mod.rs | 12 | ||||
| -rw-r--r-- | compiler/rustc_infer/src/infer/error_reporting/note.rs | 64 | ||||
| -rw-r--r-- | compiler/rustc_lint/src/levels.rs | 6 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/lint.rs | 14 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/mir/mono.rs | 40 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/consts.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_mir_build/src/thir/cx/expr.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_span/src/source_map.rs | 15 | ||||
| -rw-r--r-- | compiler/rustc_target/src/spec/i386_unknown_linux_gnu.rs | 8 | ||||
| -rw-r--r-- | compiler/rustc_target/src/spec/i486_unknown_linux_gnu.rs | 8 | ||||
| -rw-r--r-- | compiler/rustc_typeck/src/check/demand.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs | 34 |
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, |
