diff options
218 files changed, 2843 insertions, 1568 deletions
diff --git a/Cargo.lock b/Cargo.lock index f119f2050e9..7d7e44d1e5e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -267,7 +267,7 @@ checksum = "81a18687293a1546b67c246452202bbbf143d239cb43494cc163da14979082da" [[package]] name = "cargo" -version = "0.57.0" +version = "0.58.0" dependencies = [ "anyhow", "atty", @@ -2322,6 +2322,15 @@ dependencies = [ ] [[package]] +name = "odht" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b18a8d1c919d3e7b5c49708d08ef7d60bc2150a7c3a8244257c54ca3f625010" +dependencies = [ + "cfg-if 1.0.0", +] + +[[package]] name = "once_cell" version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -3859,6 +3868,7 @@ version = "0.0.0" name = "rustc_hir" version = "0.0.0" dependencies = [ + "odht", "rustc_ast", "rustc_data_structures", "rustc_feature", @@ -4045,6 +4055,7 @@ name = "rustc_metadata" version = "0.0.0" dependencies = [ "libc", + "odht", "rustc_ast", "rustc_attr", "rustc_data_structures", diff --git a/compiler/rustc_ast_lowering/src/block.rs b/compiler/rustc_ast_lowering/src/block.rs index ca804ec6758..14a894d61f4 100644 --- a/compiler/rustc_ast_lowering/src/block.rs +++ b/compiler/rustc_ast_lowering/src/block.rs @@ -55,7 +55,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } StmtKind::Item(ref it) => { - stmts.extend(self.lower_item_id(it).into_iter().enumerate().map( + stmts.extend(self.lower_item_ref(it).into_iter().enumerate().map( |(i, item_id)| { let hir_id = match i { 0 => self.lower_node_id(s.id), diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index a77e3e1997f..980036c662a 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -40,6 +40,7 @@ impl ItemLowerer<'_, '_, '_> { impl<'a> Visitor<'a> for ItemLowerer<'a, '_, '_> { fn visit_item(&mut self, item: &'a Item) { + self.lctx.allocate_hir_id_counter(item.id); let hir_id = self.lctx.with_hir_id_owner(item.id, |lctx| { lctx.without_in_scope_lifetime_defs(|lctx| { let hir_item = lctx.lower_item(item); @@ -50,12 +51,6 @@ impl<'a> Visitor<'a> for ItemLowerer<'a, '_, '_> { self.lctx.with_parent_item_lifetime_defs(hir_id, |this| { let this = &mut ItemLowerer { lctx: this }; match item.kind { - ItemKind::Mod(..) => { - let def_id = this.lctx.lower_node_id(item.id).expect_owner(); - let old_current_module = mem::replace(&mut this.lctx.current_module, def_id); - visit::walk_item(this, item); - this.lctx.current_module = old_current_module; - } ItemKind::Impl(box ImplKind { ref of_trait, .. }) => { this.with_trait_impl_ref(of_trait, |this| visit::walk_item(this, item)); } @@ -77,6 +72,7 @@ impl<'a> Visitor<'a> for ItemLowerer<'a, '_, '_> { } fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) { + self.lctx.allocate_hir_id_counter(item.id); self.lctx.with_hir_id_owner(item.id, |lctx| match ctxt { AssocCtxt::Trait => { let hir_item = lctx.lower_trait_item(item); @@ -154,41 +150,28 @@ impl<'hir> LoweringContext<'_, 'hir> { pub(super) fn lower_mod(&mut self, items: &[P<Item>], inner: Span) -> hir::Mod<'hir> { hir::Mod { inner: self.lower_span(inner), - item_ids: self.arena.alloc_from_iter(items.iter().flat_map(|x| self.lower_item_id(x))), + item_ids: self.arena.alloc_from_iter(items.iter().flat_map(|x| self.lower_item_ref(x))), } } - pub(super) fn lower_item_id(&mut self, i: &Item) -> SmallVec<[hir::ItemId; 1]> { - let node_ids = match i.kind { - ItemKind::Use(ref use_tree) => { - let mut vec = smallvec![i.id]; - self.lower_item_id_use_tree(use_tree, i.id, &mut vec); - vec - } - ItemKind::Fn(..) | ItemKind::Impl(box ImplKind { of_trait: None, .. }) => { - smallvec![i.id] - } - _ => smallvec![i.id], - }; - + pub(super) fn lower_item_ref(&mut self, i: &Item) -> SmallVec<[hir::ItemId; 1]> { + let mut node_ids = smallvec![hir::ItemId { def_id: self.resolver.local_def_id(i.id) }]; + if let ItemKind::Use(ref use_tree) = &i.kind { + self.lower_item_id_use_tree(use_tree, i.id, &mut node_ids); + } node_ids - .into_iter() - .map(|node_id| hir::ItemId { - def_id: self.allocate_hir_id_counter(node_id).expect_owner(), - }) - .collect() } fn lower_item_id_use_tree( &mut self, tree: &UseTree, base_id: NodeId, - vec: &mut SmallVec<[NodeId; 1]>, + vec: &mut SmallVec<[hir::ItemId; 1]>, ) { match tree.kind { UseTreeKind::Nested(ref nested_vec) => { for &(ref nested, id) in nested_vec { - vec.push(id); + vec.push(hir::ItemId { def_id: self.resolver.local_def_id(id) }); self.lower_item_id_use_tree(nested, id, vec); } } @@ -197,7 +180,7 @@ impl<'hir> LoweringContext<'_, 'hir> { for (_, &id) in iter::zip(self.expect_full_res_from_use(base_id).skip(1), &[id1, id2]) { - vec.push(id); + vec.push(hir::ItemId { def_id: self.resolver.local_def_id(id) }); } } } @@ -486,7 +469,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } } - let mut resolutions = self.expect_full_res_from_use(id); + let mut resolutions = self.expect_full_res_from_use(id).fuse(); // We want to return *something* from this function, so hold onto the first item // for later. let ret_res = self.lower_res(resolutions.next().unwrap_or(Res::Err)); @@ -496,7 +479,11 @@ impl<'hir> LoweringContext<'_, 'hir> { // won't be dealing with macros in the rest of the compiler. // Essentially a single `use` which imports two names is desugared into // two imports. - for (res, &new_node_id) in iter::zip(resolutions, &[id1, id2]) { + for new_node_id in [id1, id2] { + // Associate an HirId to both ids even if there is no resolution. + let new_id = self.allocate_hir_id_counter(new_node_id); + + let res = if let Some(res) = resolutions.next() { res } else { continue }; let ident = *ident; let mut path = path.clone(); for seg in &mut path.segments { @@ -505,17 +492,16 @@ impl<'hir> LoweringContext<'_, 'hir> { let span = path.span; self.with_hir_id_owner(new_node_id, |this| { - let new_id = this.lower_node_id(new_node_id); let res = this.lower_res(res); let path = this.lower_path_extra(res, &path, ParamMode::Explicit, None); let kind = hir::ItemKind::Use(path, hir::UseKind::Single); let vis = this.rebuild_vis(&vis); if let Some(attrs) = attrs { - this.attrs.insert(new_id, attrs); + this.attrs.insert(hir::HirId::make_owner(new_id), attrs); } this.insert_item(hir::Item { - def_id: new_id.expect_owner(), + def_id: new_id, ident: this.lower_ident(ident), kind, vis, @@ -564,7 +550,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // Add all the nested `PathListItem`s to the HIR. for &(ref use_tree, id) in trees { - let new_hir_id = self.lower_node_id(id); + let new_hir_id = self.allocate_hir_id_counter(id); let mut prefix = prefix.clone(); @@ -585,11 +571,11 @@ impl<'hir> LoweringContext<'_, 'hir> { let kind = this.lower_use_tree(use_tree, &prefix, id, &mut vis, &mut ident, attrs); if let Some(attrs) = attrs { - this.attrs.insert(new_hir_id, attrs); + this.attrs.insert(hir::HirId::make_owner(new_hir_id), attrs); } this.insert_item(hir::Item { - def_id: new_hir_id.expect_owner(), + def_id: new_hir_id, ident: this.lower_ident(ident), kind, vis, @@ -700,7 +686,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_foreign_item_ref(&mut self, i: &ForeignItem) -> hir::ForeignItemRef<'hir> { hir::ForeignItemRef { - id: hir::ForeignItemId { def_id: self.lower_node_id(i.id).expect_owner() }, + id: hir::ForeignItemId { def_id: self.allocate_hir_id_counter(i.id) }, ident: self.lower_ident(i.ident), span: self.lower_span(i.span), vis: self.lower_visibility(&i.vis, Some(i.id)), @@ -839,7 +825,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } AssocItemKind::MacCall(..) => unimplemented!(), }; - let id = hir::TraitItemId { def_id: self.lower_node_id(i.id).expect_owner() }; + let id = hir::TraitItemId { def_id: self.resolver.local_def_id(i.id) }; let defaultness = hir::Defaultness::Default { has_value: has_default }; hir::TraitItemRef { id, @@ -925,7 +911,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let has_value = true; let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value); hir::ImplItemRef { - id: hir::ImplItemId { def_id: self.lower_node_id(i.id).expect_owner() }, + id: hir::ImplItemId { def_id: self.allocate_hir_id_counter(i.id) }, ident: self.lower_ident(i.ident), span: self.lower_span(i.span), vis: self.lower_visibility(&i.vis, Some(i.id)), diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 4cf54b07dbe..66bcd698e6a 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -38,7 +38,7 @@ use rustc_ast::node_id::NodeMap; use rustc_ast::token::{self, Token}; use rustc_ast::tokenstream::{CanSynthesizeMissingTokens, TokenStream, TokenTree}; -use rustc_ast::visit::{self, AssocCtxt, Visitor}; +use rustc_ast::visit; use rustc_ast::{self as ast, *}; use rustc_ast_pretty::pprust; use rustc_data_structures::captures::Captures; @@ -102,8 +102,6 @@ struct LoweringContext<'a, 'hir: 'a> { owners: IndexVec<LocalDefId, Option<hir::OwnerNode<'hir>>>, bodies: BTreeMap<hir::BodyId, hir::Body<'hir>>, - modules: BTreeMap<LocalDefId, hir::ModuleItems>, - generator_kind: Option<hir::GeneratorKind>, attrs: BTreeMap<hir::HirId, &'hir [Attribute]>, @@ -152,8 +150,6 @@ struct LoweringContext<'a, 'hir: 'a> { /// vector. in_scope_lifetimes: Vec<ParamName>, - current_module: LocalDefId, - current_hir_id_owner: (LocalDefId, u32), item_local_id_counters: NodeMap<u32>, node_id_to_hir_id: IndexVec<NodeId, Option<hir::HirId>>, @@ -327,7 +323,6 @@ pub fn lower_crate<'a, 'hir>( arena, owners: IndexVec::default(), bodies: BTreeMap::new(), - modules: BTreeMap::new(), attrs: BTreeMap::default(), catch_scope: None, loop_scope: None, @@ -335,7 +330,6 @@ pub fn lower_crate<'a, 'hir>( is_in_trait_impl: false, is_in_dyn_type: false, anonymous_lifetime_mode: AnonymousLifetimeMode::PassThrough, - current_module: CRATE_DEF_ID, current_hir_id_owner: (CRATE_DEF_ID, 0), item_local_id_counters: Default::default(), node_id_to_hir_id: IndexVec::new(), @@ -418,60 +412,9 @@ enum AnonymousLifetimeMode { impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_crate(mut self, c: &Crate) -> &'hir hir::Crate<'hir> { - /// Full-crate AST visitor that inserts into a fresh - /// `LoweringContext` any information that may be - /// needed from arbitrary locations in the crate, - /// e.g., the number of lifetime generic parameters - /// declared for every type and trait definition. - struct MiscCollector<'tcx, 'lowering, 'hir> { - lctx: &'tcx mut LoweringContext<'lowering, 'hir>, - } - - impl MiscCollector<'_, '_, '_> { - fn allocate_use_tree_hir_id_counters(&mut self, tree: &UseTree) { - match tree.kind { - UseTreeKind::Simple(_, id1, id2) => { - for id in [id1, id2] { - self.lctx.allocate_hir_id_counter(id); - } - } - UseTreeKind::Glob => (), - UseTreeKind::Nested(ref trees) => { - for &(ref use_tree, id) in trees { - self.lctx.allocate_hir_id_counter(id); - self.allocate_use_tree_hir_id_counters(use_tree); - } - } - } - } - } - - impl<'tcx> Visitor<'tcx> for MiscCollector<'tcx, '_, '_> { - fn visit_item(&mut self, item: &'tcx Item) { - self.lctx.allocate_hir_id_counter(item.id); - - if let ItemKind::Use(ref use_tree) = item.kind { - self.allocate_use_tree_hir_id_counters(use_tree); - } - - visit::walk_item(self, item); - } - - fn visit_assoc_item(&mut self, item: &'tcx AssocItem, ctxt: AssocCtxt) { - self.lctx.allocate_hir_id_counter(item.id); - visit::walk_assoc_item(self, item, ctxt); - } - - fn visit_foreign_item(&mut self, item: &'tcx ForeignItem) { - self.lctx.allocate_hir_id_counter(item.id); - visit::walk_foreign_item(self, item); - } - } - self.lower_node_id(CRATE_NODE_ID); debug_assert!(self.node_id_to_hir_id[CRATE_NODE_ID] == Some(hir::CRATE_HIR_ID)); - visit::walk_crate(&mut MiscCollector { lctx: &mut self }, c); visit::walk_crate(&mut item::ItemLowerer { lctx: &mut self }, c); let module = self.arena.alloc(self.lower_mod(&c.items, c.span)); @@ -508,13 +451,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } - let krate = hir::Crate { - owners: self.owners, - bodies: self.bodies, - modules: self.modules, - trait_map, - attrs: self.attrs, - }; + let krate = + hir::Crate { owners: self.owners, bodies: self.bodies, trait_map, attrs: self.attrs }; self.arena.alloc(krate) } @@ -523,7 +461,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let item = self.arena.alloc(item); self.owners.ensure_contains_elem(id.def_id, || None); self.owners[id.def_id] = Some(hir::OwnerNode::Item(item)); - self.modules.entry(self.current_module).or_default().items.insert(id); id } @@ -532,7 +469,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let item = self.arena.alloc(item); self.owners.ensure_contains_elem(id.def_id, || None); self.owners[id.def_id] = Some(hir::OwnerNode::ForeignItem(item)); - self.modules.entry(self.current_module).or_default().foreign_items.insert(id); id } @@ -541,7 +477,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let item = self.arena.alloc(item); self.owners.ensure_contains_elem(id.def_id, || None); self.owners[id.def_id] = Some(hir::OwnerNode::ImplItem(item)); - self.modules.entry(self.current_module).or_default().impl_items.insert(id); id } @@ -550,17 +485,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let item = self.arena.alloc(item); self.owners.ensure_contains_elem(id.def_id, || None); self.owners[id.def_id] = Some(hir::OwnerNode::TraitItem(item)); - self.modules.entry(self.current_module).or_default().trait_items.insert(id); id } - fn allocate_hir_id_counter(&mut self, owner: NodeId) -> hir::HirId { + fn allocate_hir_id_counter(&mut self, owner: NodeId) -> LocalDefId { // Set up the counter if needed. self.item_local_id_counters.entry(owner).or_insert(0); // Always allocate the first `HirId` for the owner itself. let lowered = self.lower_node_id_with_owner(owner, owner); debug_assert_eq!(lowered.local_id.as_u32(), 0); - lowered + lowered.owner } fn create_stable_hashing_context(&self) -> LoweringHasher<'_> { @@ -1494,9 +1428,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // frequently opened issues show. let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::OpaqueTy, span, None); - let opaque_ty_def_id = self.resolver.local_def_id(opaque_ty_node_id); - - self.allocate_hir_id_counter(opaque_ty_node_id); + let opaque_ty_def_id = self.allocate_hir_id_counter(opaque_ty_node_id); let collected_lifetimes = self.with_hir_id_owner(opaque_ty_node_id, move |lctx| { let hir_bounds = lower_bounds(lctx); @@ -1753,9 +1685,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::Async, span, None); - let opaque_ty_def_id = self.resolver.local_def_id(opaque_ty_node_id); - - self.allocate_hir_id_counter(opaque_ty_node_id); + let opaque_ty_def_id = self.allocate_hir_id_counter(opaque_ty_node_id); // When we create the opaque type for this async fn, it is going to have // to capture all the lifetimes involved in the signature (including in the diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 30bc4edd7e6..06e9d9ed329 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -702,10 +702,16 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) { } fn maybe_stage_features(sess: &Session, krate: &ast::Crate) { + // checks if `#![feature]` has been used to enable any lang feature + // does not check the same for lib features unless there's at least one + // declared lang feature use rustc_errors::Applicability; if !sess.opts.unstable_features.is_nightly_build() { let lang_features = &sess.features_untracked().declared_lang_features; + if lang_features.len() == 0 { + return; + } for attr in krate.attrs.iter().filter(|attr| attr.has_name(sym::feature)) { let mut err = struct_span_err!( sess.parse_sess.span_diagnostic, diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index 3c114084586..b23ce281bef 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -336,15 +336,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { if def_id.as_local() == Some(self.mir_def_id()) && upvar_field.is_some() => { let closure_kind_ty = closure_substs.as_closure().kind_ty(); - let closure_kind = closure_kind_ty.to_opt_closure_kind(); - let capture_description = match closure_kind { - Some(ty::ClosureKind::Fn) => "captured variable in an `Fn` closure", - Some(ty::ClosureKind::FnMut) => "captured variable in an `FnMut` closure", + let closure_kind = match closure_kind_ty.to_opt_closure_kind() { + Some(kind @ (ty::ClosureKind::Fn | ty::ClosureKind::FnMut)) => kind, Some(ty::ClosureKind::FnOnce) => { bug!("closure kind does not match first argument type") } None => bug!("closure kind not inferred by borrowck"), }; + let capture_description = + format!("captured variable in an `{}` closure", closure_kind); let upvar = &self.upvars[upvar_field.unwrap().index()]; let upvar_hir_id = upvar.place.get_root_variable(); @@ -368,6 +368,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let mut diag = self.cannot_move_out_of(span, &place_description); diag.span_label(upvar_span, "captured outer variable"); + diag.span_label( + self.body.span, + format!("captured by this `{}` closure", closure_kind), + ); diag } diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 57d2a3c5ce9..0761d63c665 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -40,6 +40,7 @@ impl ConstraintDescription for ConstraintCategory { ConstraintCategory::CopyBound => "copying this value ", ConstraintCategory::OpaqueType => "opaque type ", ConstraintCategory::ClosureUpvar(_) => "closure capture ", + ConstraintCategory::Usage => "this usage ", ConstraintCategory::Boring | ConstraintCategory::BoringNoLocation | ConstraintCategory::Internal => "", diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index 39b83e50431..d790e31105c 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -46,7 +46,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// Calling `universal_upper_bound` for such a region gives `fr_fn_body`, /// which has no `external_name` in which case we use `'empty` as the /// region to pass to `infer_opaque_definition_from_instantiation`. - #[instrument(skip(self, infcx))] + #[instrument(level = "debug", skip(self, infcx))] pub(crate) fn infer_opaque_types( &self, infcx: &InferCtxt<'_, 'tcx>, diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 41c004ea596..5ccf3806025 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1388,11 +1388,24 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ConstraintCategory::Return(ReturnConstraint::Normal) } } + Some(l) + if matches!( + body.local_decls[l].local_info, + Some(box LocalInfo::AggregateTemp) + ) => + { + ConstraintCategory::Usage + } Some(l) if !body.local_decls[l].is_user_variable() => { ConstraintCategory::Boring } _ => ConstraintCategory::Assignment, }; + debug!( + "assignment category: {:?} {:?}", + category, + place.as_local().map(|l| &body.local_decls[l]) + ); let place_ty = place.ty(body, tcx).ty; let place_ty = self.normalize(place_ty, location); diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs index 13790409e59..15bb9067805 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs @@ -5,7 +5,7 @@ mod pass_mode; mod returning; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; -use rustc_middle::ty::layout::FnAbiExt; +use rustc_middle::ty::layout::FnAbiOf; use rustc_target::abi::call::{Conv, FnAbi}; use rustc_target::spec::abi::Abi; @@ -53,7 +53,11 @@ pub(crate) fn get_function_sig<'tcx>( inst: Instance<'tcx>, ) -> Signature { assert!(!inst.substs.needs_infer()); - clif_sig_from_fn_abi(tcx, triple, &FnAbi::of_instance(&RevealAllLayoutCx(tcx), inst, &[])) + clif_sig_from_fn_abi( + tcx, + triple, + &RevealAllLayoutCx(tcx).fn_abi_of_instance(inst, ty::List::empty()), + ) } /// Instance must be monomorphized @@ -350,14 +354,13 @@ pub(crate) fn codegen_terminator_call<'tcx>( }; let extra_args = &args[fn_sig.inputs().len()..]; - let extra_args = extra_args - .iter() - .map(|op_arg| fx.monomorphize(op_arg.ty(fx.mir, fx.tcx))) - .collect::<Vec<_>>(); + let extra_args = fx + .tcx + .mk_type_list(extra_args.iter().map(|op_arg| fx.monomorphize(op_arg.ty(fx.mir, fx.tcx)))); let fn_abi = if let Some(instance) = instance { - FnAbi::of_instance(&RevealAllLayoutCx(fx.tcx), instance, &extra_args) + RevealAllLayoutCx(fx.tcx).fn_abi_of_instance(instance, extra_args) } else { - FnAbi::of_fn_ptr(&RevealAllLayoutCx(fx.tcx), fn_ty.fn_sig(fx.tcx), &extra_args) + RevealAllLayoutCx(fx.tcx).fn_abi_of_fn_ptr(fn_ty.fn_sig(fx.tcx), extra_args) }; let is_cold = instance @@ -525,7 +528,8 @@ pub(crate) fn codegen_drop<'tcx>( def: ty::InstanceDef::Virtual(drop_instance.def_id(), 0), substs: drop_instance.substs, }; - let fn_abi = FnAbi::of_instance(&RevealAllLayoutCx(fx.tcx), virtual_drop, &[]); + let fn_abi = + RevealAllLayoutCx(fx.tcx).fn_abi_of_instance(virtual_drop, ty::List::empty()); let sig = clif_sig_from_fn_abi(fx.tcx, fx.triple(), &fn_abi); let sig = fx.bcx.import_signature(sig); @@ -534,7 +538,8 @@ pub(crate) fn codegen_drop<'tcx>( _ => { assert!(!matches!(drop_instance.def, InstanceDef::Virtual(_, _))); - let fn_abi = FnAbi::of_instance(&RevealAllLayoutCx(fx.tcx), drop_instance, &[]); + let fn_abi = + RevealAllLayoutCx(fx.tcx).fn_abi_of_instance(drop_instance, ty::List::empty()); let arg_value = drop_place.place_ref( fx, diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index d29558a4e1f..d8fa2c76904 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -3,8 +3,7 @@ use cranelift_codegen::binemit::{NullStackMapSink, NullTrapSink}; use rustc_index::vec::IndexVec; use rustc_middle::ty::adjustment::PointerCast; -use rustc_middle::ty::layout::FnAbiExt; -use rustc_target::abi::call::FnAbi; +use rustc_middle::ty::layout::FnAbiOf; use crate::constant::ConstantCx; use crate::prelude::*; @@ -62,7 +61,7 @@ pub(crate) fn codegen_fn<'tcx>( instance, symbol_name, mir, - fn_abi: Some(FnAbi::of_instance(&RevealAllLayoutCx(tcx), instance, &[])), + fn_abi: Some(RevealAllLayoutCx(tcx).fn_abi_of_instance(instance, ty::List::empty())), bcx, block_map, diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs index 6f7ca51d038..0e84681d9ad 100644 --- a/compiler/rustc_codegen_cranelift/src/common.rs +++ b/compiler/rustc_codegen_cranelift/src/common.rs @@ -1,5 +1,7 @@ use rustc_index::vec::IndexVec; -use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers}; +use rustc_middle::ty::layout::{ + FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers, +}; use rustc_middle::ty::SymbolName; use rustc_target::abi::call::FnAbi; use rustc_target::abi::{Integer, Primitive}; @@ -239,7 +241,7 @@ pub(crate) struct FunctionCx<'m, 'clif, 'tcx: 'm> { pub(crate) instance: Instance<'tcx>, pub(crate) symbol_name: SymbolName<'tcx>, pub(crate) mir: &'tcx Body<'tcx>, - pub(crate) fn_abi: Option<FnAbi<'tcx, Ty<'tcx>>>, + pub(crate) fn_abi: Option<&'tcx FnAbi<'tcx, Ty<'tcx>>>, pub(crate) bcx: FunctionBuilder<'clif>, pub(crate) block_map: IndexVec<BasicBlock, Block>, @@ -266,6 +268,20 @@ impl<'tcx> LayoutOfHelpers<'tcx> for FunctionCx<'_, '_, 'tcx> { } } +impl<'tcx> FnAbiOfHelpers<'tcx> for FunctionCx<'_, '_, 'tcx> { + type FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>; + + #[inline] + fn handle_fn_abi_err( + &self, + err: FnAbiError<'tcx>, + span: Span, + fn_abi_request: FnAbiRequest<'tcx>, + ) -> ! { + RevealAllLayoutCx(self.tcx).handle_fn_abi_err(err, span, fn_abi_request) + } +} + impl<'tcx> layout::HasTyCtxt<'tcx> for FunctionCx<'_, '_, 'tcx> { fn tcx<'b>(&'b self) -> TyCtxt<'tcx> { self.tcx @@ -378,6 +394,43 @@ impl<'tcx> LayoutOfHelpers<'tcx> for RevealAllLayoutCx<'tcx> { } } +impl<'tcx> FnAbiOfHelpers<'tcx> for RevealAllLayoutCx<'tcx> { + type FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>; + + #[inline] + fn handle_fn_abi_err( + &self, + err: FnAbiError<'tcx>, + span: Span, + fn_abi_request: FnAbiRequest<'tcx>, + ) -> ! { + if let FnAbiError::Layout(LayoutError::SizeOverflow(_)) = err { + self.0.sess.span_fatal(span, &err.to_string()) + } else { + match fn_abi_request { + FnAbiRequest::OfFnPtr { sig, extra_args } => { + span_bug!( + span, + "`fn_abi_of_fn_ptr({}, {:?})` failed: {}", + sig, + extra_args, + err + ); + } + FnAbiRequest::OfInstance { instance, extra_args } => { + span_bug!( + span, + "`fn_abi_of_instance({}, {:?})` failed: {}", + instance, + extra_args, + err + ); + } + } + } + } +} + impl<'tcx> layout::HasTyCtxt<'tcx> for RevealAllLayoutCx<'tcx> { fn tcx<'b>(&'b self) -> TyCtxt<'tcx> { self.0 diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index 424a0d742d1..5c4991f1fb6 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -129,9 +129,7 @@ pub(crate) fn codegen_constant<'tcx>( }; let const_val = match const_.val { ConstKind::Value(const_val) => const_val, - ConstKind::Unevaluated(uv) - if fx.tcx.is_static(uv.def.did) => - { + ConstKind::Unevaluated(uv) if fx.tcx.is_static(uv.def.did) => { assert!(uv.substs(fx.tcx).is_empty()); assert!(uv.promoted.is_none()); diff --git a/compiler/rustc_codegen_cranelift/src/pretty_clif.rs b/compiler/rustc_codegen_cranelift/src/pretty_clif.rs index 05db74745a1..ec846d71960 100644 --- a/compiler/rustc_codegen_cranelift/src/pretty_clif.rs +++ b/compiler/rustc_codegen_cranelift/src/pretty_clif.rs @@ -61,9 +61,8 @@ use cranelift_codegen::{ write::{FuncWriter, PlainWriter}, }; -use rustc_middle::ty::layout::FnAbiExt; +use rustc_middle::ty::layout::FnAbiOf; use rustc_session::config::OutputType; -use rustc_target::abi::call::FnAbi; use crate::prelude::*; @@ -81,7 +80,10 @@ impl CommentWriter { vec![ format!("symbol {}", tcx.symbol_name(instance).name), format!("instance {:?}", instance), - format!("abi {:?}", FnAbi::of_instance(&RevealAllLayoutCx(tcx), instance, &[])), + format!( + "abi {:?}", + RevealAllLayoutCx(tcx).fn_abi_of_instance(instance, ty::List::empty()) + ), String::new(), ] } else { diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 799f9a57e93..dab7d3eaa8c 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -15,10 +15,12 @@ use rustc_codegen_ssa::traits::*; use rustc_codegen_ssa::MemFlags; use rustc_data_structures::small_c_str::SmallCStr; use rustc_hir::def_id::DefId; -use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout}; +use rustc_middle::ty::layout::{ + FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers, TyAndLayout, +}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::Span; -use rustc_target::abi::{self, Align, Size, WrappingRange}; +use rustc_target::abi::{self, call::FnAbi, Align, Size, WrappingRange}; use rustc_target::spec::{HasTargetSpec, Target}; use std::borrow::Cow; use std::ffi::CStr; @@ -97,6 +99,20 @@ impl LayoutOfHelpers<'tcx> for Builder<'_, '_, 'tcx> { } } +impl FnAbiOfHelpers<'tcx> for Builder<'_, '_, 'tcx> { + type FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>; + + #[inline] + fn handle_fn_abi_err( + &self, + err: FnAbiError<'tcx>, + span: Span, + fn_abi_request: FnAbiRequest<'tcx>, + ) -> ! { + self.cx.handle_fn_abi_err(err, span, fn_abi_request) + } +} + impl Deref for Builder<'_, 'll, 'tcx> { type Target = CodegenCx<'ll, 'tcx>; diff --git a/compiler/rustc_codegen_llvm/src/callee.rs b/compiler/rustc_codegen_llvm/src/callee.rs index bb16c90cd12..a96ba148a6c 100644 --- a/compiler/rustc_codegen_llvm/src/callee.rs +++ b/compiler/rustc_codegen_llvm/src/callee.rs @@ -4,7 +4,7 @@ //! and methods are represented as just a fn ptr and not a full //! closure. -use crate::abi::{FnAbi, FnAbiLlvmExt}; +use crate::abi::FnAbiLlvmExt; use crate::attributes; use crate::context::CodegenCx; use crate::llvm; @@ -12,7 +12,7 @@ use crate::value::Value; use rustc_codegen_ssa::traits::*; use tracing::debug; -use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt}; +use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt}; use rustc_middle::ty::{self, Instance, TypeFoldable}; /// Codegens a reference to a fn/method item, monomorphizing and @@ -42,7 +42,7 @@ pub fn get_fn(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) -> &'ll Value sym ); - let fn_abi = FnAbi::of_instance(cx, instance, &[]); + let fn_abi = cx.fn_abi_of_instance(instance, ty::List::empty()); let llfn = if let Some(llfn) = cx.get_declared_value(&sym) { // Create a fn pointer with the new signature. diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 2d397dc5835..52a12b2fd81 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -15,14 +15,19 @@ use rustc_data_structures::base_n; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::small_c_str::SmallCStr; use rustc_middle::mir::mono::CodegenUnit; -use rustc_middle::ty::layout::{HasParamEnv, LayoutError, LayoutOfHelpers, TyAndLayout}; +use rustc_middle::ty::layout::{ + FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, LayoutError, LayoutOfHelpers, + TyAndLayout, +}; use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; use rustc_middle::{bug, span_bug}; use rustc_session::config::{CFGuard, CrateType, DebugInfo}; use rustc_session::Session; use rustc_span::source_map::Span; use rustc_span::symbol::Symbol; -use rustc_target::abi::{HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx}; +use rustc_target::abi::{ + call::FnAbi, HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx, +}; use rustc_target::spec::{HasTargetSpec, RelocModel, Target, TlsModel}; use smallvec::SmallVec; @@ -835,6 +840,12 @@ impl ty::layout::HasTyCtxt<'tcx> for CodegenCx<'ll, 'tcx> { } } +impl<'tcx, 'll> HasParamEnv<'tcx> for CodegenCx<'ll, 'tcx> { + fn param_env(&self) -> ty::ParamEnv<'tcx> { + ty::ParamEnv::reveal_all() + } +} + impl LayoutOfHelpers<'tcx> for CodegenCx<'ll, 'tcx> { type LayoutOfResult = TyAndLayout<'tcx>; @@ -848,8 +859,39 @@ impl LayoutOfHelpers<'tcx> for CodegenCx<'ll, 'tcx> { } } -impl<'tcx, 'll> HasParamEnv<'tcx> for CodegenCx<'ll, 'tcx> { - fn param_env(&self) -> ty::ParamEnv<'tcx> { - ty::ParamEnv::reveal_all() +impl FnAbiOfHelpers<'tcx> for CodegenCx<'ll, 'tcx> { + type FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>; + + #[inline] + fn handle_fn_abi_err( + &self, + err: FnAbiError<'tcx>, + span: Span, + fn_abi_request: FnAbiRequest<'tcx>, + ) -> ! { + if let FnAbiError::Layout(LayoutError::SizeOverflow(_)) = err { + self.sess().span_fatal(span, &err.to_string()) + } else { + match fn_abi_request { + FnAbiRequest::OfFnPtr { sig, extra_args } => { + span_bug!( + span, + "`fn_abi_of_fn_ptr({}, {:?})` failed: {}", + sig, + extra_args, + err + ); + } + FnAbiRequest::OfInstance { instance, extra_args } => { + span_bug!( + span, + "`fn_abi_of_instance({}, {:?})` failed: {}", + instance, + extra_args, + err + ); + } + } + } } } diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs index 019bf4a09a7..093aceda2b7 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs @@ -1,6 +1,6 @@ use crate::llvm; -use crate::abi::{Abi, FnAbi}; +use crate::abi::Abi; use crate::builder::Builder; use crate::common::CodegenCx; @@ -20,7 +20,7 @@ use rustc_middle::mir::coverage::{ CodeRegion, CounterValueReference, ExpressionOperandId, InjectedExpressionId, Op, }; use rustc_middle::ty; -use rustc_middle::ty::layout::FnAbiExt; +use rustc_middle::ty::layout::FnAbiOf; use rustc_middle::ty::subst::InternalSubsts; use rustc_middle::ty::Instance; @@ -200,8 +200,7 @@ fn declare_unused_fn(cx: &CodegenCx<'ll, 'tcx>, def_id: &DefId) -> Instance<'tcx let llfn = cx.declare_fn( &tcx.symbol_name(instance).name, - &FnAbi::of_fn_ptr( - cx, + &cx.fn_abi_of_fn_ptr( ty::Binder::dummy(tcx.mk_fn_sig( iter::once(tcx.mk_unit()), tcx.mk_unit(), @@ -209,7 +208,7 @@ fn declare_unused_fn(cx: &CodegenCx<'ll, 'tcx>, def_id: &DefId) -> Instance<'tcx hir::Unsafety::Unsafe, Abi::Rust, )), - &[], + ty::List::empty(), ), ); diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs index c2725b83f50..1612922d439 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs @@ -3,12 +3,11 @@ use super::utils::DIB; use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext}; use rustc_codegen_ssa::traits::*; -use crate::abi::FnAbi; use crate::common::CodegenCx; use crate::llvm; use crate::llvm::debuginfo::{DILocation, DIScope}; use rustc_middle::mir::{Body, SourceScope}; -use rustc_middle::ty::layout::FnAbiExt; +use rustc_middle::ty::layout::FnAbiOf; use rustc_middle::ty::{self, Instance}; use rustc_session::config::DebugInfo; @@ -94,7 +93,7 @@ fn make_mir_scope( ty::ParamEnv::reveal_all(), callee, ); - let callee_fn_abi = FnAbi::of_instance(cx, callee, &[]); + let callee_fn_abi = cx.fn_abi_of_instance(callee, ty::List::empty()); cx.dbg_scope_fn(callee, &callee_fn_abi, None) } None => unsafe { diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 1060f911a9e..37b3279fb80 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -15,7 +15,7 @@ use rustc_codegen_ssa::mir::operand::OperandRef; use rustc_codegen_ssa::mir::place::PlaceRef; use rustc_codegen_ssa::traits::*; use rustc_hir as hir; -use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt, LayoutOf}; +use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, LayoutOf}; use rustc_middle::ty::{self, Ty}; use rustc_middle::{bug, span_bug}; use rustc_span::{sym, symbol::kw, Span, Symbol}; @@ -737,7 +737,7 @@ fn gen_fn<'ll, 'tcx>( rust_fn_sig: ty::PolyFnSig<'tcx>, codegen: &mut dyn FnMut(Builder<'_, 'll, 'tcx>), ) -> (&'ll Type, &'ll Value) { - let fn_abi = FnAbi::of_fn_ptr(cx, rust_fn_sig, &[]); + let fn_abi = cx.fn_abi_of_fn_ptr(rust_fn_sig, ty::List::empty()); let llty = fn_abi.llvm_type(cx); let llfn = cx.declare_fn(name, &fn_abi); cx.set_frame_pointer_type(llfn); @@ -918,12 +918,29 @@ fn generic_simd_intrinsic( } if let Some(stripped) = name_str.strip_prefix("simd_shuffle") { - let n: u64 = stripped.parse().unwrap_or_else(|_| { - span_bug!(span, "bad `simd_shuffle` instruction only caught in codegen?") - }); + // If this intrinsic is the older "simd_shuffleN" form, simply parse the integer. + // If there is no suffix, use the index array length. + let n: u64 = if stripped.is_empty() { + // Make sure this is actually an array, since typeck only checks the length-suffixed + // version of this intrinsic. + match args[2].layout.ty.kind() { + ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => { + len.try_eval_usize(bx.cx.tcx, ty::ParamEnv::reveal_all()).unwrap_or_else(|| { + span_bug!(span, "could not evaluate shuffle index array length") + }) + } + _ => return_error!( + "simd_shuffle index must be an array of `u32`, got `{}`", + args[2].layout.ty + ), + } + } else { + stripped.parse().unwrap_or_else(|_| { + span_bug!(span, "bad `simd_shuffle` instruction only caught in codegen?") + }) + }; require_simd!(ret_ty, "return"); - let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx()); require!( out_len == n, diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs index 8ba3e870fbb..34982f769d0 100644 --- a/compiler/rustc_codegen_llvm/src/mono_item.rs +++ b/compiler/rustc_codegen_llvm/src/mono_item.rs @@ -1,4 +1,3 @@ -use crate::abi::FnAbi; use crate::attributes; use crate::base; use crate::context::CodegenCx; @@ -8,7 +7,7 @@ use rustc_codegen_ssa::traits::*; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; pub use rustc_middle::mir::mono::MonoItem; use rustc_middle::mir::mono::{Linkage, Visibility}; -use rustc_middle::ty::layout::{FnAbiExt, LayoutOf}; +use rustc_middle::ty::layout::{FnAbiOf, LayoutOf}; use rustc_middle::ty::{self, Instance, TypeFoldable}; use rustc_session::config::CrateType; use rustc_target::spec::RelocModel; @@ -53,7 +52,7 @@ impl PreDefineMethods<'tcx> for CodegenCx<'ll, 'tcx> { ) { assert!(!instance.substs.needs_infer()); - let fn_abi = FnAbi::of_instance(self, instance, &[]); + let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty()); let lldecl = self.declare_fn(symbol_name, &fn_abi); unsafe { llvm::LLVMRustSetLinkage(lldecl, base::linkage_to_llvm(linkage)) }; let attrs = self.tcx.codegen_fn_attrs(instance.def_id()); diff --git a/compiler/rustc_codegen_llvm/src/type_of.rs b/compiler/rustc_codegen_llvm/src/type_of.rs index 3e39bf3e995..757ccbddbee 100644 --- a/compiler/rustc_codegen_llvm/src/type_of.rs +++ b/compiler/rustc_codegen_llvm/src/type_of.rs @@ -1,10 +1,9 @@ -use crate::abi::FnAbi; use crate::common::*; use crate::context::TypeLowering; use crate::type_::Type; use rustc_codegen_ssa::traits::*; use rustc_middle::bug; -use rustc_middle::ty::layout::{FnAbiExt, LayoutOf, TyAndLayout}; +use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, TyAndLayout}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, Ty, TypeFoldable}; use rustc_target::abi::{Abi, AddressSpace, Align, FieldsShape}; @@ -231,7 +230,9 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> { ty::Adt(def, _) if def.is_box() => { cx.type_ptr_to(cx.layout_of(self.ty.boxed_ty()).llvm_type(cx)) } - ty::FnPtr(sig) => cx.fn_ptr_backend_type(&FnAbi::of_fn_ptr(cx, sig, &[])), + ty::FnPtr(sig) => { + cx.fn_ptr_backend_type(&cx.fn_abi_of_fn_ptr(sig, ty::List::empty())) + } _ => self.scalar_llvm_type_at(cx, scalar, Size::ZERO), }; cx.scalar_lltypes.borrow_mut().insert(self.ty, llty); diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index cd0e9354c24..4be050fb88c 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -14,7 +14,7 @@ use rustc_hir::lang_items::LangItem; use rustc_index::vec::Idx; use rustc_middle::mir::AssertKind; use rustc_middle::mir::{self, SwitchTargets}; -use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt, LayoutOf}; +use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, Instance, Ty, TypeFoldable}; use rustc_span::source_map::Span; @@ -124,7 +124,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { &self, fx: &mut FunctionCx<'a, 'tcx, Bx>, bx: &mut Bx, - fn_abi: FnAbi<'tcx, Ty<'tcx>>, + fn_abi: &'tcx FnAbi<'tcx, Ty<'tcx>>, fn_ptr: Bx::Value, llargs: &[Bx::Value], destination: Option<(ReturnDest<'tcx, Bx::Value>, mir::BasicBlock)>, @@ -337,7 +337,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { def: ty::InstanceDef::Virtual(drop_fn.def_id(), 0), substs: drop_fn.substs, }; - let fn_abi = FnAbi::of_instance(&bx, virtual_drop, &[]); + let fn_abi = bx.fn_abi_of_instance(virtual_drop, ty::List::empty()); let vtable = args[1]; args = &args[..1]; ( @@ -346,7 +346,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { fn_abi, ) } - _ => (bx.get_fn_addr(drop_fn), FnAbi::of_instance(&bx, drop_fn, &[])), + _ => (bx.get_fn_addr(drop_fn), bx.fn_abi_of_instance(drop_fn, ty::List::empty())), }; helper.do_call( self, @@ -433,7 +433,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // Obtain the panic entry point. let def_id = common::langcall(bx.tcx(), Some(span), "", lang_item); let instance = ty::Instance::mono(bx.tcx(), def_id); - let fn_abi = FnAbi::of_instance(&bx, instance, &[]); + let fn_abi = bx.fn_abi_of_instance(instance, ty::List::empty()); let llfn = bx.get_fn_addr(instance); // Codegen the actual panic invoke/call. @@ -494,7 +494,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let def_id = common::langcall(bx.tcx(), Some(source_info.span), "", LangItem::Panic); let instance = ty::Instance::mono(bx.tcx(), def_id); - let fn_abi = FnAbi::of_instance(bx, instance, &[]); + let fn_abi = bx.fn_abi_of_instance(instance, ty::List::empty()); let llfn = bx.get_fn_addr(instance); // Codegen the actual panic invoke/call. @@ -570,17 +570,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }; let extra_args = &args[sig.inputs().skip_binder().len()..]; - let extra_args = extra_args - .iter() - .map(|op_arg| { - let op_ty = op_arg.ty(self.mir, bx.tcx()); - self.monomorphize(op_ty) - }) - .collect::<Vec<_>>(); + let extra_args = bx.tcx().mk_type_list(extra_args.iter().map(|op_arg| { + let op_ty = op_arg.ty(self.mir, bx.tcx()); + self.monomorphize(op_ty) + })); let fn_abi = match instance { - Some(instance) => FnAbi::of_instance(&bx, instance, &extra_args), - None => FnAbi::of_fn_ptr(&bx, sig, &extra_args), + Some(instance) => bx.fn_abi_of_instance(instance, extra_args), + None => bx.fn_abi_of_fn_ptr(sig, extra_args), }; if intrinsic == Some(sym::transmute) { @@ -665,8 +662,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { if i == 2 && intrinsic.as_str().starts_with("simd_shuffle") { if let mir::Operand::Constant(constant) = arg { let c = self.eval_mir_constant(constant); - let (llval, ty) = - self.simd_shuffle_indices(&bx, constant.span, constant.ty(), c); + let (llval, ty) = self.simd_shuffle_indices( + &bx, + constant.span, + self.monomorphize(constant.ty()), + c, + ); return OperandRef { val: Immediate(llval), layout: bx.layout_of(ty), diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index e2edd448267..8e3982c72d7 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -2,7 +2,7 @@ use crate::traits::*; use rustc_errors::ErrorReported; use rustc_middle::mir; use rustc_middle::mir::interpret::ErrorHandled; -use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt, TyAndLayout}; +use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, TyAndLayout}; use rustc_middle::ty::{self, Instance, Ty, TypeFoldable}; use rustc_target::abi::call::{FnAbi, PassMode}; @@ -29,7 +29,7 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { cx: &'a Bx::CodegenCx, - fn_abi: FnAbi<'tcx, Ty<'tcx>>, + fn_abi: &'tcx FnAbi<'tcx, Ty<'tcx>>, /// When unwinding is initiated, we have to store this personality /// value somewhere so that we can load it and re-use it in the @@ -139,7 +139,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let mir = cx.tcx().instance_mir(instance.def); - let fn_abi = FnAbi::of_instance(cx, instance, &[]); + let fn_abi = cx.fn_abi_of_instance(instance, ty::List::empty()); debug!("fn_abi: {:?}", fn_abi); let debug_context = cx.create_function_debug_context(instance, &fn_abi, llfn, &mir); @@ -152,20 +152,11 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( } let cleanup_kinds = analyze::cleanup_kinds(&mir); - // Allocate a `Block` for every basic block, except - // the start block, if nothing loops back to it. - let reentrant_start_block = !mir.predecessors()[mir::START_BLOCK].is_empty(); - let cached_llbbs: IndexVec<mir::BasicBlock, Option<Bx::BasicBlock>> = - mir.basic_blocks() - .indices() - .map(|bb| { - if bb == mir::START_BLOCK && !reentrant_start_block { - Some(start_llbb) - } else { - None - } - }) - .collect(); + let cached_llbbs: IndexVec<mir::BasicBlock, Option<Bx::BasicBlock>> = mir + .basic_blocks() + .indices() + .map(|bb| if bb == mir::START_BLOCK { Some(start_llbb) } else { None }) + .collect(); let mut fx = FunctionCx { instance, @@ -247,11 +238,6 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // Apply debuginfo to the newly allocated locals. fx.debug_introduce_locals(&mut bx); - // Branch to the START block, if it's not the entry block. - if reentrant_start_block { - bx.br(fx.llbb(mir::START_BLOCK)); - } - // Codegen the body of each block using reverse postorder // FIXME(eddyb) reuse RPO iterator between `analysis` and this. for (bb, _) in traversal::reverse_postorder(&mir) { diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs index dbb7e1ee8b1..82b79fd0b2a 100644 --- a/compiler/rustc_codegen_ssa/src/traits/backend.rs +++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs @@ -8,14 +8,15 @@ use rustc_data_structures::fx::FxHashMap; use rustc_errors::ErrorReported; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; use rustc_middle::middle::cstore::{EncodedMetadata, MetadataLoaderDyn}; -use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout}; +use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, LayoutOf, TyAndLayout}; use rustc_middle::ty::query::Providers; -use rustc_middle::ty::TyCtxt; +use rustc_middle::ty::{Ty, TyCtxt}; use rustc_session::{ config::{self, OutputFilenames, PrintRequest}, Session, }; use rustc_span::symbol::Symbol; +use rustc_target::abi::call::FnAbi; use rustc_target::spec::Target; pub use rustc_data_structures::sync::MetadataRef; @@ -38,12 +39,19 @@ pub trait BackendTypes { } pub trait Backend<'tcx>: - Sized + BackendTypes + HasTyCtxt<'tcx> + LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>> + Sized + + BackendTypes + + HasTyCtxt<'tcx> + + LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>> + + FnAbiOf<'tcx, FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>> { } impl<'tcx, T> Backend<'tcx> for T where - Self: BackendTypes + HasTyCtxt<'tcx> + LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>> + Self: BackendTypes + + HasTyCtxt<'tcx> + + LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>> + + FnAbiOf<'tcx, FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>> { } diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 8a90686b900..ae20f6f97b2 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -36,12 +36,17 @@ impl<'mir, 'tcx> InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>> { let def_id = instance.def_id(); if Some(def_id) == self.tcx.lang_items().panic_fn() || Some(def_id) == self.tcx.lang_items().panic_str() + || Some(def_id) == self.tcx.lang_items().panic_display() || Some(def_id) == self.tcx.lang_items().begin_panic_fn() { - // &str + // &str or &&str assert!(args.len() == 1); - let msg_place = self.deref_operand(&args[0])?; + let mut msg_place = self.deref_operand(&args[0])?; + while msg_place.layout.ty.is_ref() { + msg_place = self.deref_operand(&msg_place.into())?; + } + let msg = Symbol::intern(self.read_str(&msg_place)?); let span = self.find_closest_untracked_caller_location(); let (file, line, col) = self.location_triple_for_span(span); diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index d5682f702ba..9eec930f59e 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -384,11 +384,11 @@ impl Checker<'mir, 'tcx> { match pred.skip_binder() { ty::ExistentialPredicate::AutoTrait(_) | ty::ExistentialPredicate::Projection(_) => { - self.check_op(ops::ty::TraitBound(kind)) + self.check_op(ops::ty::DynTrait(kind)) } ty::ExistentialPredicate::Trait(trait_ref) => { if Some(trait_ref.def_id) != self.tcx.lang_items().sized_trait() { - self.check_op(ops::ty::TraitBound(kind)) + self.check_op(ops::ty::DynTrait(kind)) } } } @@ -888,6 +888,10 @@ impl Visitor<'tcx> for Checker<'mir, 'tcx> { if is_lang_panic_fn(tcx, callee) { self.check_op(ops::Panic); + // `begin_panic` and `panic_display` are generic functions that accept + // types other than str. Check to enforce that only str can be used in + // const-eval. + // const-eval of the `begin_panic` fn assumes the argument is `&str` if Some(callee) == tcx.lang_items().begin_panic_fn() { match args[0].ty(&self.ccx.body.local_decls, tcx).kind() { @@ -896,6 +900,15 @@ impl Visitor<'tcx> for Checker<'mir, 'tcx> { } } + // const-eval of the `panic_display` fn assumes the argument is `&&str` + if Some(callee) == tcx.lang_items().panic_display() { + match args[0].ty(&self.ccx.body.local_decls, tcx).kind() { + ty::Ref(_, ty, _) if matches!(ty.kind(), ty::Ref(_, ty, _) if ty.is_str()) => + {} + _ => self.check_op(ops::PanicNonStr), + } + } + return; } diff --git a/compiler/rustc_const_eval/src/transform/check_consts/mod.rs b/compiler/rustc_const_eval/src/transform/check_consts/mod.rs index a5cb0f4e14b..d1fd3ceaa58 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/mod.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/mod.rs @@ -79,6 +79,7 @@ pub fn is_lang_panic_fn(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool { // Keep in sync with what that function handles! Some(def_id) == tcx.lang_items().panic_fn() || Some(def_id) == tcx.lang_items().panic_str() + || Some(def_id) == tcx.lang_items().panic_display() || Some(def_id) == tcx.lang_items().begin_panic_fn() || Some(def_id) == tcx.lang_items().panic_fmt() || Some(def_id) == tcx.lang_items().begin_panic_fmt() diff --git a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs index 2a296750838..1d0ee949a22 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs @@ -599,7 +599,7 @@ pub mod ty { } fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { - let mut builder = feature_err( + let mut err = feature_err( &ccx.tcx.sess.parse_sess, sym::const_fn_trait_bound, span, @@ -608,12 +608,51 @@ pub mod ty { match ccx.fn_sig() { Some(fn_sig) if !fn_sig.span.contains(span) => { - builder.span_label(fn_sig.span, "function declared as const here"); + err.span_label(fn_sig.span, "function declared as const here"); } _ => {} } - builder + err + } + } + + #[derive(Debug)] + pub struct DynTrait(pub mir::LocalKind); + impl NonConstOp for DynTrait { + fn importance(&self) -> DiagnosticImportance { + match self.0 { + mir::LocalKind::Var | mir::LocalKind::Temp => DiagnosticImportance::Secondary, + mir::LocalKind::ReturnPointer | mir::LocalKind::Arg => { + DiagnosticImportance::Primary + } + } + } + + fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status { + if ccx.const_kind() != hir::ConstContext::ConstFn { + Status::Allowed + } else { + Status::Unstable(sym::const_fn_trait_bound) + } + } + + fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + let mut err = feature_err( + &ccx.tcx.sess.parse_sess, + sym::const_fn_trait_bound, + span, + "trait objects in const fn are unstable", + ); + + match ccx.fn_sig() { + Some(fn_sig) if !fn_sig.span.contains(span) => { + err.span_label(fn_sig.span, "function declared as const here"); + } + _ => {} + } + + err } } diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs index dc3927ed85b..cb9b4bcb77a 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs @@ -111,7 +111,17 @@ impl Qualif for NeedsNonConstDrop { qualifs.needs_drop } - fn in_any_value_of_ty(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool { + fn in_any_value_of_ty(cx: &ConstCx<'_, 'tcx>, mut ty: Ty<'tcx>) -> bool { + // Avoid selecting for simple cases. + match ty::util::needs_drop_components(ty, &cx.tcx.data_layout).as_deref() { + Ok([]) => return false, + Err(ty::util::AlwaysRequiresDrop) => return true, + // If we've got a single component, select with that + // to increase the chance that we hit the selection cache. + Ok([t]) => ty = t, + Ok([..]) => {} + } + let drop_trait = if let Some(did) = cx.tcx.lang_items().drop_trait() { did } else { diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index 40a32a76c94..b09b2227f3e 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -9,7 +9,7 @@ use rustc_middle::mir::visit::{PlaceContext, Visitor}; use rustc_middle::mir::{ AggregateKind, BasicBlock, Body, BorrowKind, Local, Location, MirPhase, Operand, PlaceElem, PlaceRef, ProjectionElem, Rvalue, SourceScope, Statement, StatementKind, Terminator, - TerminatorKind, + TerminatorKind, START_BLOCK, }; use rustc_middle::ty::fold::BottomUpFolder; use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, TypeFoldable}; @@ -130,6 +130,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } fn check_edge(&self, location: Location, bb: BasicBlock, edge_kind: EdgeKind) { + if bb == START_BLOCK { + self.fail(location, "start block must not have predecessors") + } if let Some(bb) = self.body.basic_blocks().get(bb) { let src = self.body.basic_blocks().get(location.block).unwrap(); match (src.is_cleanup, bb.is_cleanup, edge_kind) { diff --git a/compiler/rustc_error_codes/src/error_codes/E0071.md b/compiler/rustc_error_codes/src/error_codes/E0071.md index bc2c03a0220..a6d6d19762b 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0071.md +++ b/compiler/rustc_error_codes/src/error_codes/E0071.md @@ -15,13 +15,13 @@ form of initializer was used. For example, the code above can be fixed to: ``` -enum Foo { - FirstValue(i32) -} +type U32 = u32; +let t: U32 = 4; +``` -fn main() { - let u = Foo::FirstValue(0i32); +or: - let t = 4; -} +``` +struct U32 { value: u32 } +let t = U32 { value: 4 }; ``` diff --git a/compiler/rustc_error_codes/src/error_codes/E0439.md b/compiler/rustc_error_codes/src/error_codes/E0439.md index 3e663df866c..24268aef222 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0439.md +++ b/compiler/rustc_error_codes/src/error_codes/E0439.md @@ -1,8 +1,10 @@ +#### Note: this error code is no longer emitted by the compiler. + The length of the platform-intrinsic function `simd_shuffle` wasn't specified. Erroneous code example: -```compile_fail,E0439 +```ignore (no longer emitted) #![feature(platform_intrinsics)] extern "platform-intrinsic" { diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 62066ca9657..d32593f34ad 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -1386,14 +1386,17 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { // `SEMICOLON_IN_EXPRESSIONS_FROM_MACROS` lint if needed. // See #78991 for an investigation of treating macros in this position // as statements, rather than expressions, during parsing. - if let StmtKind::Expr(expr) = &stmt.kind { - if matches!(**expr, ast::Expr { kind: ast::ExprKind::MacCall(..), .. }) { + let res = match &stmt.kind { + StmtKind::Expr(expr) + if matches!(**expr, ast::Expr { kind: ast::ExprKind::MacCall(..), .. }) => + { self.cx.current_expansion.is_trailing_mac = true; + // Don't use `assign_id` for this statement - it may get removed + // entirely due to a `#[cfg]` on the contained expression + noop_flat_map_stmt(stmt, self) } - } - - let res = assign_id!(self, &mut stmt.id, || noop_flat_map_stmt(stmt, self)); - + _ => assign_id!(self, &mut stmt.id, || noop_flat_map_stmt(stmt, self)), + }; self.cx.current_expansion.is_trailing_mac = false; res } diff --git a/compiler/rustc_hir/Cargo.toml b/compiler/rustc_hir/Cargo.toml index c92551c2930..ff6758e66df 100644 --- a/compiler/rustc_hir/Cargo.toml +++ b/compiler/rustc_hir/Cargo.toml @@ -17,3 +17,4 @@ rustc_serialize = { path = "../rustc_serialize" } rustc_ast = { path = "../rustc_ast" } tracing = "0.1" smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } +odht = { version = "0.2.1", features = ["nightly"] } diff --git a/compiler/rustc_hir/src/def_path_hash_map.rs b/compiler/rustc_hir/src/def_path_hash_map.rs new file mode 100644 index 00000000000..8bfb47af26f --- /dev/null +++ b/compiler/rustc_hir/src/def_path_hash_map.rs @@ -0,0 +1,37 @@ +use rustc_data_structures::fingerprint::Fingerprint; +use rustc_span::def_id::{DefIndex, DefPathHash}; + +#[derive(Clone, Default)] +pub struct Config; + +impl odht::Config for Config { + type Key = DefPathHash; + type Value = DefIndex; + + type EncodedKey = [u8; 16]; + type EncodedValue = [u8; 4]; + + type H = odht::UnHashFn; + + #[inline] + fn encode_key(k: &DefPathHash) -> [u8; 16] { + k.0.to_le_bytes() + } + + #[inline] + fn encode_value(v: &DefIndex) -> [u8; 4] { + v.as_u32().to_le_bytes() + } + + #[inline] + fn decode_key(k: &[u8; 16]) -> DefPathHash { + DefPathHash(Fingerprint::from_le_bytes(*k)) + } + + #[inline] + fn decode_value(v: &[u8; 4]) -> DefIndex { + DefIndex::from_u32(u32::from_le_bytes(*v)) + } +} + +pub type DefPathHashMap = odht::HashTableOwned<Config>; diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs index 5f56f3a32ad..ca29351455e 100644 --- a/compiler/rustc_hir/src/definitions.rs +++ b/compiler/rustc_hir/src/definitions.rs @@ -6,11 +6,11 @@ pub use crate::def_id::DefPathHash; use crate::def_id::{CrateNum, DefIndex, LocalDefId, StableCrateId, CRATE_DEF_INDEX, LOCAL_CRATE}; +use crate::def_path_hash_map::DefPathHashMap; use crate::hir; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::StableHasher; -use rustc_data_structures::unhash::UnhashMap; use rustc_index::vec::IndexVec; use rustc_span::hygiene::ExpnId; use rustc_span::symbol::{kw, sym, Symbol}; @@ -28,7 +28,7 @@ use tracing::debug; pub struct DefPathTable { index_to_key: IndexVec<DefIndex, DefKey>, def_path_hashes: IndexVec<DefIndex, DefPathHash>, - def_path_hash_to_index: UnhashMap<DefPathHash, DefIndex>, + def_path_hash_to_index: DefPathHashMap, } impl DefPathTable { @@ -44,7 +44,7 @@ impl DefPathTable { // Check for hash collisions of DefPathHashes. These should be // exceedingly rare. - if let Some(existing) = self.def_path_hash_to_index.insert(def_path_hash, index) { + if let Some(existing) = self.def_path_hash_to_index.insert(&def_path_hash, &index) { let def_path1 = DefPath::make(LOCAL_CRATE, existing, |idx| self.def_key(idx)); let def_path2 = DefPath::make(LOCAL_CRATE, index, |idx| self.def_key(idx)); @@ -87,7 +87,7 @@ impl DefPathTable { pub fn enumerated_keys_and_path_hashes( &self, - ) -> impl Iterator<Item = (DefIndex, &DefKey, &DefPathHash)> + '_ { + ) -> impl Iterator<Item = (DefIndex, &DefKey, &DefPathHash)> + ExactSizeIterator + '_ { self.index_to_key .iter_enumerated() .map(move |(index, key)| (index, key, &self.def_path_hashes[index])) @@ -110,6 +110,9 @@ pub struct Definitions { expansions_that_defined: FxHashMap<LocalDefId, ExpnId>, def_id_to_span: IndexVec<LocalDefId, Span>, + + /// The [StableCrateId] of the local crate. + stable_crate_id: StableCrateId, } /// A unique identifier that we can use to lookup a definition @@ -356,6 +359,7 @@ impl Definitions { hir_id_to_def_id: Default::default(), expansions_that_defined: Default::default(), def_id_to_span, + stable_crate_id, } } @@ -439,11 +443,17 @@ impl Definitions { } #[inline(always)] - pub fn local_def_path_hash_to_def_id(&self, hash: DefPathHash) -> Option<LocalDefId> { + pub fn local_def_path_hash_to_def_id(&self, hash: DefPathHash) -> LocalDefId { + debug_assert!(hash.stable_crate_id() == self.stable_crate_id); self.table .def_path_hash_to_index .get(&hash) - .map(|&local_def_index| LocalDefId { local_def_index }) + .map(|local_def_index| LocalDefId { local_def_index }) + .unwrap() + } + + pub fn def_path_hash_to_def_index_map(&self) -> &DefPathHashMap { + &self.table.def_path_hash_to_index } } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 5655c4c0e97..f5fc693ce25 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -21,7 +21,7 @@ use rustc_target::asm::InlineAsmRegOrRegClass; use rustc_target::spec::abi::Abi; use smallvec::SmallVec; -use std::collections::{BTreeMap, BTreeSet}; +use std::collections::BTreeMap; use std::fmt; #[derive(Copy, Clone, Encodable, HashStable_Generic)] @@ -653,16 +653,6 @@ pub struct WhereEqPredicate<'hir> { pub rhs_ty: &'hir Ty<'hir>, } -#[derive(Default, Encodable, Debug, HashStable_Generic)] -pub struct ModuleItems { - // Use BTreeSets here so items are in the same order as in the - // list of all items in Crate - pub items: BTreeSet<ItemId>, - pub trait_items: BTreeSet<TraitItemId>, - pub impl_items: BTreeSet<ImplItemId>, - pub foreign_items: BTreeSet<ForeignItemId>, -} - /// The top-level data structure that stores the entire contents of /// the crate currently being compiled. /// @@ -674,10 +664,6 @@ pub struct Crate<'hir> { pub owners: IndexVec<LocalDefId, Option<OwnerNode<'hir>>>, pub bodies: BTreeMap<BodyId, Body<'hir>>, - /// A list of modules written out in the order in which they - /// appear in the crate. This includes the main crate module. - pub modules: BTreeMap<LocalDefId, ModuleItems>, - /// Map indicating what traits are in scope for places where this /// is relevant; generated by resolve. pub trait_map: FxHashMap<LocalDefId, FxHashMap<ItemLocalId, Box<[TraitCandidate]>>>, diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index b85ed0cb4bb..d69a2470540 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -283,6 +283,7 @@ language_item_table! { // a weak lang item, but do not have it defined. Panic, sym::panic, panic_fn, Target::Fn, GenericRequirement::None; PanicFmt, sym::panic_fmt, panic_fmt, Target::Fn, GenericRequirement::None; + PanicDisplay, sym::panic_display, panic_display, Target::Fn, GenericRequirement::None; PanicStr, sym::panic_str, panic_str, Target::Fn, GenericRequirement::None; ConstPanicFmt, sym::const_panic_fmt, const_panic_fmt, Target::Fn, GenericRequirement::None; PanicBoundsCheck, sym::panic_bounds_check, panic_bounds_check_fn, Target::Fn, GenericRequirement::None; diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs index 42575273839..ce36648d6df 100644 --- a/compiler/rustc_hir/src/lib.rs +++ b/compiler/rustc_hir/src/lib.rs @@ -16,6 +16,7 @@ extern crate rustc_data_structures; mod arena; pub mod def; +pub mod def_path_hash_map; pub mod definitions; pub use rustc_span::def_id; mod hir; diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs index 593d06bad7b..35c8786dcd3 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs @@ -39,7 +39,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { ObligationCauseCode::MatchImpl(parent, impl_def_id) => (parent, impl_def_id), _ => return None, }; - let binding_span = match **parent { + let binding_span = match parent.code { ObligationCauseCode::BindingObligation(_def_id, binding_span) => binding_span, _ => return None, }; diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs index 81059fbcb10..2d47e72780e 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -189,7 +189,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { } if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = &sub_origin { let code = match &cause.code { - ObligationCauseCode::MatchImpl(parent, ..) => &**parent, + ObligationCauseCode::MatchImpl(parent, ..) => &parent.code, _ => &cause.code, }; if let ObligationCauseCode::ItemObligation(item_def_id) = *code { diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 1f3d6f70ff8..cb7529b527e 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -8,7 +8,7 @@ use rustc_borrowck as mir_borrowck; use rustc_codegen_ssa::back::link::emit_metadata; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_data_structures::parallel; -use rustc_data_structures::sync::{par_iter, Lrc, OnceCell, ParallelIterator, WorkerLocal}; +use rustc_data_structures::sync::{Lrc, OnceCell, WorkerLocal}; use rustc_data_structures::temp_dir::MaybeTempDir; use rustc_errors::{ErrorReported, PResult}; use rustc_expand::base::ExtCtxt; @@ -861,7 +861,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { CStore::from_tcx(tcx).report_unused_deps(tcx); }, { - par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| { + tcx.hir().par_for_each_module(|module| { tcx.ensure().check_mod_loops(module); tcx.ensure().check_mod_attrs(module); tcx.ensure().check_mod_naked_functions(module); @@ -893,7 +893,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { }, { sess.time("liveness_and_intrinsic_checking", || { - par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| { + tcx.hir().par_for_each_module(|module| { // this must run before MIR dump, because // "not all control paths return a value" is reported here. // @@ -963,7 +963,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { }, { sess.time("privacy_checking_modules", || { - par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| { + tcx.hir().par_for_each_module(|module| { tcx.ensure().check_mod_privacy(module); }); }); diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs index 2070fd69d3f..00c3a6fa25e 100644 --- a/compiler/rustc_lint/src/late.rs +++ b/compiler/rustc_lint/src/late.rs @@ -16,7 +16,7 @@ use crate::{passes::LateLintPassObject, LateContext, LateLintPass, LintStore}; use rustc_ast as ast; -use rustc_data_structures::sync::{join, par_iter, ParallelIterator}; +use rustc_data_structures::sync::join; use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit as hir_visit; @@ -501,9 +501,7 @@ pub fn check_crate<'tcx, T: LateLintPass<'tcx>>( || { tcx.sess.time("module_lints", || { // Run per-module lints - par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| { - tcx.ensure().lint_mod(module); - }); + tcx.hir().par_for_each_module(|module| tcx.ensure().lint_mod(module)); }); }, ); diff --git a/compiler/rustc_metadata/Cargo.toml b/compiler/rustc_metadata/Cargo.toml index 7c79aa5e00b..42596f3318d 100644 --- a/compiler/rustc_metadata/Cargo.toml +++ b/compiler/rustc_metadata/Cargo.toml @@ -8,6 +8,7 @@ doctest = false [dependencies] libc = "0.2" +odht = { version = "0.2.1", features = ["nightly"] } snap = "1" tracing = "0.1" smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 99030febb73..48d8cdf57dc 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -45,7 +45,7 @@ pub struct CStore { /// This map is used to verify we get no hash conflicts between /// `StableCrateId` values. - stable_crate_ids: FxHashMap<StableCrateId, CrateNum>, + pub(crate) stable_crate_ids: FxHashMap<StableCrateId, CrateNum>, /// Unused externs of the crate unused_externs: Vec<Symbol>, diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 2a0332a1124..eb3a9f576a7 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -48,7 +48,26 @@ use rustc_span::hygiene::HygieneDecodeContext; mod cstore_impl; -crate struct MetadataBlob(MetadataRef); +/// A reference to the raw binary version of crate metadata. +/// A `MetadataBlob` internally is just a reference counted pointer to +/// the actual data, so cloning it is cheap. +#[derive(Clone)] +crate struct MetadataBlob(Lrc<MetadataRef>); + +// This is needed so we can create an OwningRef into the blob. +// The data behind a `MetadataBlob` has a stable address because it is +// contained within an Rc/Arc. +unsafe impl rustc_data_structures::owning_ref::StableAddress for MetadataBlob {} + +// This is needed so we can create an OwningRef into the blob. +impl std::ops::Deref for MetadataBlob { + type Target = [u8]; + + #[inline] + fn deref(&self) -> &[u8] { + &self.0[..] + } +} // A map from external crate numbers (as decoded from some crate file) to // local crate numbers (as generated during this session). Each external @@ -76,10 +95,8 @@ crate struct CrateMetadata { raw_proc_macros: Option<&'static [ProcMacro]>, /// Source maps for code from the crate. source_map_import_info: OnceCell<Vec<ImportedSourceFile>>, - /// For every definition in this crate, maps its `DefPathHash` to its - /// `DefIndex`. See `raw_def_id_to_def_id` for more details about how - /// this is used. - def_path_hash_map: OnceCell<UnhashMap<DefPathHash, DefIndex>>, + /// For every definition in this crate, maps its `DefPathHash` to its `DefIndex`. + def_path_hash_map: DefPathHashMapRef<'static>, /// Likewise for ExpnHash. expn_hash_map: OnceCell<UnhashMap<ExpnHash, ExpnIndex>>, /// Used for decoding interpret::AllocIds in a cached & thread-safe manner. @@ -134,6 +151,7 @@ struct ImportedSourceFile { pub(super) struct DecodeContext<'a, 'tcx> { opaque: opaque::Decoder<'a>, cdata: Option<CrateMetadataRef<'a>>, + blob: &'a MetadataBlob, sess: Option<&'tcx Session>, tcx: Option<TyCtxt<'tcx>>, @@ -148,7 +166,8 @@ pub(super) struct DecodeContext<'a, 'tcx> { /// Abstract over the various ways one can create metadata decoders. pub(super) trait Metadata<'a, 'tcx>: Copy { - fn raw_bytes(self) -> &'a [u8]; + fn blob(self) -> &'a MetadataBlob; + fn cdata(self) -> Option<CrateMetadataRef<'a>> { None } @@ -162,8 +181,9 @@ pub(super) trait Metadata<'a, 'tcx>: Copy { fn decoder(self, pos: usize) -> DecodeContext<'a, 'tcx> { let tcx = self.tcx(); DecodeContext { - opaque: opaque::Decoder::new(self.raw_bytes(), pos), + opaque: opaque::Decoder::new(self.blob(), pos), cdata: self.cdata(), + blob: self.blob(), sess: self.sess().or(tcx.map(|tcx| tcx.sess)), tcx, last_source_file_index: 0, @@ -176,17 +196,19 @@ pub(super) trait Metadata<'a, 'tcx>: Copy { } impl<'a, 'tcx> Metadata<'a, 'tcx> for &'a MetadataBlob { - fn raw_bytes(self) -> &'a [u8] { - &self.0 + #[inline] + fn blob(self) -> &'a MetadataBlob { + self } } impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a MetadataBlob, &'tcx Session) { - fn raw_bytes(self) -> &'a [u8] { - let (blob, _) = self; - &blob.0 + #[inline] + fn blob(self) -> &'a MetadataBlob { + self.0 } + #[inline] fn sess(self) -> Option<&'tcx Session> { let (_, sess) = self; Some(sess) @@ -194,33 +216,41 @@ impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a MetadataBlob, &'tcx Session) { } impl<'a, 'tcx> Metadata<'a, 'tcx> for &'a CrateMetadataRef<'a> { - fn raw_bytes(self) -> &'a [u8] { - self.blob.raw_bytes() + #[inline] + fn blob(self) -> &'a MetadataBlob { + &self.blob } + #[inline] fn cdata(self) -> Option<CrateMetadataRef<'a>> { Some(*self) } } impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadataRef<'a>, &'tcx Session) { - fn raw_bytes(self) -> &'a [u8] { - self.0.raw_bytes() + #[inline] + fn blob(self) -> &'a MetadataBlob { + &self.0.blob } + #[inline] fn cdata(self) -> Option<CrateMetadataRef<'a>> { Some(*self.0) } + #[inline] fn sess(self) -> Option<&'tcx Session> { Some(&self.1) } } impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadataRef<'a>, TyCtxt<'tcx>) { - fn raw_bytes(self) -> &'a [u8] { - self.0.raw_bytes() + #[inline] + fn blob(self) -> &'a MetadataBlob { + &self.0.blob } + #[inline] fn cdata(self) -> Option<CrateMetadataRef<'a>> { Some(*self.0) } + #[inline] fn tcx(self) -> Option<TyCtxt<'tcx>> { Some(self.1) } @@ -246,12 +276,21 @@ impl<'a: 'x, 'tcx: 'x, 'x, T: Decodable<DecodeContext<'a, 'tcx>>> Lazy<[T]> { } impl<'a, 'tcx> DecodeContext<'a, 'tcx> { + #[inline] fn tcx(&self) -> TyCtxt<'tcx> { - self.tcx.expect("missing TyCtxt in DecodeContext") + debug_assert!(self.tcx.is_some(), "missing TyCtxt in DecodeContext"); + self.tcx.unwrap() + } + + #[inline] + pub fn blob(&self) -> &'a MetadataBlob { + self.blob } - fn cdata(&self) -> CrateMetadataRef<'a> { - self.cdata.expect("missing CrateMetadata in DecodeContext") + #[inline] + pub fn cdata(&self) -> CrateMetadataRef<'a> { + debug_assert!(self.cdata.is_some(), "missing CrateMetadata in DecodeContext"); + self.cdata.unwrap() } fn map_encoded_cnum_to_current(&self, cnum: CrateNum) -> CrateNum { @@ -276,6 +315,11 @@ impl<'a, 'tcx> DecodeContext<'a, 'tcx> { self.lazy_state = LazyState::Previous(NonZeroUsize::new(position + min_size).unwrap()); Ok(Lazy::from_position_and_meta(NonZeroUsize::new(position).unwrap(), meta)) } + + #[inline] + pub fn read_raw_bytes(&mut self, len: usize) -> &'a [u8] { + self.opaque.read_raw_bytes(len) + } } impl<'a, 'tcx> TyDecoder<'tcx> for DecodeContext<'a, 'tcx> { @@ -586,11 +630,11 @@ implement_ty_decoder!(DecodeContext<'a, 'tcx>); impl MetadataBlob { crate fn new(metadata_ref: MetadataRef) -> MetadataBlob { - MetadataBlob(metadata_ref) + MetadataBlob(Lrc::new(metadata_ref)) } crate fn is_compatible(&self) -> bool { - self.raw_bytes().starts_with(METADATA_HEADER) + self.blob().starts_with(METADATA_HEADER) } crate fn get_rustc_version(&self) -> String { @@ -599,7 +643,7 @@ impl MetadataBlob { } crate fn get_root(&self) -> CrateRoot<'tcx> { - let slice = self.raw_bytes(); + let slice = &self.blob()[..]; let offset = METADATA_HEADER.len(); let pos = (((slice[offset + 0] as u32) << 24) | ((slice[offset + 1] as u32) << 16) @@ -1552,58 +1596,6 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .or_insert_with(|| self.root.tables.def_keys.get(self, index).unwrap().decode(self)) } - /// Finds the corresponding `DefId` for the provided `DefPathHash`, if it exists. - /// This is used by incremental compilation to map a serialized `DefPathHash` to - /// its `DefId` in the current session. - /// Normally, only one 'main' crate will change between incremental compilation sessions: - /// all dependencies will be completely unchanged. In this case, we can avoid - /// decoding every `DefPathHash` in the crate, since the `DefIndex` from the previous - /// session will still be valid. If our 'guess' is wrong (the `DefIndex` no longer exists, - /// or has a different `DefPathHash`, then we need to decode all `DefPathHashes` to determine - /// the correct mapping). - fn def_path_hash_to_def_id( - &self, - krate: CrateNum, - index_guess: u32, - hash: DefPathHash, - ) -> Option<DefId> { - let def_index_guess = DefIndex::from_u32(index_guess); - let old_hash = self - .root - .tables - .def_path_hashes - .get(self, def_index_guess) - .map(|lazy| lazy.decode(self)); - - // Fast path: the definition and its index is unchanged from the - // previous compilation session. There is no need to decode anything - // else - if old_hash == Some(hash) { - return Some(DefId { krate, index: def_index_guess }); - } - - let is_proc_macro = self.is_proc_macro_crate(); - - // Slow path: We need to find out the new `DefIndex` of the provided - // `DefPathHash`, if its still exists. This requires decoding every `DefPathHash` - // stored in this crate. - let map = self.cdata.def_path_hash_map.get_or_init(|| { - let end_id = self.root.tables.def_path_hashes.size() as u32; - let mut map = UnhashMap::with_capacity_and_hasher(end_id as usize, Default::default()); - for i in 0..end_id { - let def_index = DefIndex::from_u32(i); - // There may be gaps in the encoded table if we're decoding a proc-macro crate - if let Some(hash) = self.root.tables.def_path_hashes.get(self, def_index) { - map.insert(hash.decode(self), def_index); - } else if !is_proc_macro { - panic!("Missing def_path_hashes entry for {:?}", def_index); - } - } - map - }); - map.get(&hash).map(|index| DefId { krate, index: *index }) - } - // Returns the path leading to the thing with this `id`. fn def_path(&self, id: DefIndex) -> DefPath { debug!("def_path(cnum={:?}, id={:?})", self.cnum, id); @@ -1626,6 +1618,11 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { self.def_path_hash_unlocked(index, &mut def_path_hashes) } + #[inline] + fn def_path_hash_to_def_index(&self, hash: DefPathHash) -> DefIndex { + self.def_path_hash_map.def_path_hash_to_def_index(&hash) + } + fn expn_hash_to_expn_id(&self, index_guess: u32, hash: ExpnHash) -> ExpnId { debug_assert_eq!(ExpnId::from_hash(hash), None); let index_guess = ExpnIndex::from_u32(index_guess); @@ -1892,13 +1889,18 @@ impl CrateMetadata { let alloc_decoding_state = AllocDecodingState::new(root.interpret_alloc_index.decode(&blob).collect()); let dependencies = Lock::new(cnum_map.iter().cloned().collect()); + + // Pre-decode the DefPathHash->DefIndex table. This is a cheap operation + // that does not copy any data. It just does some data verification. + let def_path_hash_map = root.def_path_hash_map.decode(&blob); + CrateMetadata { blob, root, trait_impls, raw_proc_macros, source_map_import_info: OnceCell::new(), - def_path_hash_map: Default::default(), + def_path_hash_map, expn_hash_map: Default::default(), alloc_decoding_state, cnum, diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index a01eaf68f01..70952d388d5 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -498,6 +498,10 @@ impl CrateStore for CStore { self.get_crate_data(cnum).root.stable_crate_id } + fn stable_crate_id_to_crate_num(&self, stable_crate_id: StableCrateId) -> CrateNum { + self.stable_crate_ids[&stable_crate_id] + } + /// Returns the `DefKey` for a given `DefId`. This indicates the /// parent `DefId` as well as some idea of what kind of data the /// `DefId` refers to. @@ -513,14 +517,9 @@ impl CrateStore for CStore { self.get_crate_data(def.krate).def_path_hash(def.index) } - // See `CrateMetadataRef::def_path_hash_to_def_id` for more details - fn def_path_hash_to_def_id( - &self, - cnum: CrateNum, - index_guess: u32, - hash: DefPathHash, - ) -> Option<DefId> { - self.get_crate_data(cnum).def_path_hash_to_def_id(cnum, index_guess, hash) + fn def_path_hash_to_def_id(&self, cnum: CrateNum, hash: DefPathHash) -> DefId { + let def_index = self.get_crate_data(cnum).def_path_hash_to_def_index(hash); + DefId { krate: cnum, index: def_index } } fn expn_hash_to_expn_id(&self, cnum: CrateNum, index_guess: u32, hash: ExpnHash) -> ExpnId { diff --git a/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs b/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs new file mode 100644 index 00000000000..d6435bb649d --- /dev/null +++ b/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs @@ -0,0 +1,58 @@ +use crate::rmeta::DecodeContext; +use crate::rmeta::EncodeContext; +use crate::rmeta::MetadataBlob; +use rustc_data_structures::owning_ref::OwningRef; +use rustc_hir::def_path_hash_map::{Config as HashMapConfig, DefPathHashMap}; +use rustc_serialize::{opaque, Decodable, Decoder, Encodable, Encoder}; +use rustc_span::def_id::{DefIndex, DefPathHash}; + +crate enum DefPathHashMapRef<'tcx> { + OwnedFromMetadata(odht::HashTable<HashMapConfig, OwningRef<MetadataBlob, [u8]>>), + BorrowedFromTcx(&'tcx DefPathHashMap), +} + +impl DefPathHashMapRef<'tcx> { + #[inline] + pub fn def_path_hash_to_def_index(&self, def_path_hash: &DefPathHash) -> DefIndex { + match *self { + DefPathHashMapRef::OwnedFromMetadata(ref map) => map.get(def_path_hash).unwrap(), + DefPathHashMapRef::BorrowedFromTcx(_) => { + panic!("DefPathHashMap::BorrowedFromTcx variant only exists for serialization") + } + } + } +} + +impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for DefPathHashMapRef<'tcx> { + fn encode(&self, e: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult { + match *self { + DefPathHashMapRef::BorrowedFromTcx(def_path_hash_map) => { + let bytes = def_path_hash_map.raw_bytes(); + e.emit_usize(bytes.len())?; + e.emit_raw_bytes(bytes) + } + DefPathHashMapRef::OwnedFromMetadata(_) => { + panic!("DefPathHashMap::OwnedFromMetadata variant only exists for deserialization") + } + } + } +} + +impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for DefPathHashMapRef<'static> { + fn decode(d: &mut DecodeContext<'a, 'tcx>) -> Result<DefPathHashMapRef<'static>, String> { + // Import TyDecoder so we can access the DecodeContext::position() method + use crate::rustc_middle::ty::codec::TyDecoder; + + let len = d.read_usize()?; + let pos = d.position(); + let o = OwningRef::new(d.blob().clone()).map(|x| &x[pos..pos + len]); + + // Although we already have the data we need via the OwningRef, we still need + // to advance the DecodeContext's position so it's in a valid state after + // the method. We use read_raw_bytes() for that. + let _ = d.read_raw_bytes(len); + + let inner = odht::HashTable::from_raw_bytes(o).map_err(|e| format!("{}", e))?; + Ok(DefPathHashMapRef::OwnedFromMetadata(inner)) + } +} diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index b0d22037f21..a50c4549d3d 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1,3 +1,4 @@ +use crate::rmeta::def_path_hash_map::DefPathHashMapRef; use crate::rmeta::table::{FixedSizeEncoding, TableBuilder}; use crate::rmeta::*; @@ -472,6 +473,12 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } } + fn encode_def_path_hash_map(&mut self) -> Lazy<DefPathHashMapRef<'tcx>> { + self.lazy(DefPathHashMapRef::BorrowedFromTcx( + self.tcx.resolutions(()).definitions.def_path_hash_to_def_index_map(), + )) + } + fn encode_source_map(&mut self) -> Lazy<[rustc_span::SourceFile]> { let source_map = self.tcx.sess.source_map(); let all_source_files = source_map.files(); @@ -675,6 +682,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let (syntax_contexts, expn_data, expn_hashes) = self.encode_hygiene(); let hygiene_bytes = self.position() - i; + i = self.position(); + let def_path_hash_map = self.encode_def_path_hash_map(); + let def_path_hash_map_bytes = self.position() - i; + // Encode source_map. This needs to be done last, // since encoding `Span`s tells us which `SourceFiles` we actually // need to encode. @@ -722,6 +733,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { syntax_contexts, expn_data, expn_hashes, + def_path_hash_map, }); let total_bytes = self.position(); @@ -744,6 +756,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { eprintln!(" impl bytes: {}", impl_bytes); eprintln!(" exp. symbols bytes: {}", exported_symbols_bytes); eprintln!(" def-path table bytes: {}", def_path_table_bytes); + eprintln!(" def-path hashes bytes: {}", def_path_hash_map_bytes); eprintln!(" proc-macro-data-bytes: {}", proc_macro_data_bytes); eprintln!(" mir bytes: {}", mir_bytes); eprintln!(" item bytes: {}", item_bytes); diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 1f307f3fdee..eb2bd80f46e 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -1,4 +1,5 @@ use decoder::Metadata; +use def_path_hash_map::DefPathHashMapRef; use table::{Table, TableBuilder}; use rustc_ast::{self as ast, MacroDef}; @@ -35,6 +36,7 @@ use encoder::EncodeContext; use rustc_span::hygiene::SyntaxContextData; mod decoder; +mod def_path_hash_map; mod encoder; mod table; @@ -231,6 +233,8 @@ crate struct CrateRoot<'tcx> { expn_data: ExpnDataTable, expn_hashes: ExpnHashTable, + def_path_hash_map: Lazy<DefPathHashMapRef<'tcx>>, + source_map: Lazy<[rustc_span::SourceFile]>, compiler_builtins: bool, diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs index 62c0ce15845..4dfefda490b 100644 --- a/compiler/rustc_metadata/src/rmeta/table.rs +++ b/compiler/rustc_metadata/src/rmeta/table.rs @@ -199,7 +199,7 @@ where debug!("Table::lookup: index={:?} len={:?}", i, self.meta); let start = self.position.get(); - let bytes = &metadata.raw_bytes()[start..start + self.meta]; + let bytes = &metadata.blob()[start..start + self.meta]; <Option<T>>::maybe_read_from_bytes_at(bytes, i.index())? } diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 59db2c6636f..2dd43a4e852 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -11,7 +11,8 @@ macro_rules! arena_types { ($macro:path, $tcx:lifetime) => ( $macro!([ - [] layouts: rustc_target::abi::Layout, + [] layout: rustc_target::abi::Layout, + [] fn_abi: rustc_target::abi::call::FnAbi<$tcx, rustc_middle::ty::Ty<$tcx>>, // AdtDef are interned and compared by address [] adt_def: rustc_middle::ty::AdtDef, [] steal_thir: rustc_data_structures::steal::Steal<rustc_middle::thir::Thir<$tcx>>, diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index 8476929eaec..e788dd4be85 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -336,7 +336,11 @@ impl DepNodeExt for DepNode { /// has been removed. fn extract_def_id(&self, tcx: TyCtxt<'tcx>) -> Option<DefId> { if self.kind.can_reconstruct_query_key() { - tcx.on_disk_cache.as_ref()?.def_path_hash_to_def_id(tcx, DefPathHash(self.hash.into())) + Some( + tcx.on_disk_cache + .as_ref()? + .def_path_hash_to_def_id(tcx, DefPathHash(self.hash.into())), + ) } else { None } @@ -385,17 +389,7 @@ impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for DefId { } fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { - let hash = tcx.def_path_hash(*self); - // If this is a foreign `DefId`, store its current value - // in the incremental cache. When we decode the cache, - // we will use the old DefIndex as an initial guess for - // a lookup into the crate metadata. - if !self.is_local() { - if let Some(cache) = &tcx.on_disk_cache { - cache.store_foreign_def_id_hash(*self, hash); - } - } - hash.0 + tcx.def_path_hash(*self).0 } fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { diff --git a/compiler/rustc_middle/src/dep_graph/mod.rs b/compiler/rustc_middle/src/dep_graph/mod.rs index aa61219ad78..35dc1631db3 100644 --- a/compiler/rustc_middle/src/dep_graph/mod.rs +++ b/compiler/rustc_middle/src/dep_graph/mod.rs @@ -92,12 +92,7 @@ impl<'tcx> DepContext for TyCtxt<'tcx> { type DepKind = DepKind; type StableHashingContext = StableHashingContext<'tcx>; - fn register_reused_dep_node(&self, dep_node: &DepNode) { - if let Some(cache) = self.on_disk_cache.as_ref() { - cache.register_reused_dep_node(*self, dep_node) - } - } - + #[inline] fn create_stable_hashing_context(&self) -> Self::StableHashingContext { TyCtxt::create_stable_hashing_context(*self) } diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 10714a4b706..0c2c653e92e 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -1,13 +1,13 @@ use self::collector::NodeCollector; -use crate::hir::{AttributeMap, IndexedHir, Owner}; +use crate::hir::{AttributeMap, IndexedHir, ModuleItems, Owner}; use crate::ty::TyCtxt; use rustc_ast as ast; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::svh::Svh; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_ID, CRATE_DEF_INDEX, LOCAL_CRATE}; +use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE}; use rustc_hir::definitions::{DefKey, DefPath, DefPathHash}; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::itemlikevisit::ItemLikeVisitor; @@ -19,6 +19,7 @@ use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::Span; use rustc_target::spec::abi::Abi; +use std::collections::VecDeque; pub mod blocks; mod collector; @@ -206,11 +207,6 @@ impl<'hir> Map<'hir> { } pub fn opt_def_kind(&self, local_def_id: LocalDefId) -> Option<DefKind> { - // FIXME(eddyb) support `find` on the crate root. - if local_def_id.to_def_id().index == CRATE_DEF_INDEX { - return Some(DefKind::Mod); - } - let hir_id = self.local_def_id_to_hir_id(local_def_id); let def_kind = match self.find(hir_id)? { Node::Item(item) => match item.kind { @@ -541,23 +537,55 @@ impl<'hir> Map<'hir> { { let module = self.tcx.hir_module_items(module); - for id in &module.items { + for id in module.items.iter() { visitor.visit_item(self.item(*id)); } - for id in &module.trait_items { + for id in module.trait_items.iter() { visitor.visit_trait_item(self.trait_item(*id)); } - for id in &module.impl_items { + for id in module.impl_items.iter() { visitor.visit_impl_item(self.impl_item(*id)); } - for id in &module.foreign_items { + for id in module.foreign_items.iter() { visitor.visit_foreign_item(self.foreign_item(*id)); } } + pub fn for_each_module(&self, f: impl Fn(LocalDefId)) { + let mut queue = VecDeque::new(); + queue.push_back(CRATE_DEF_ID); + + while let Some(id) = queue.pop_front() { + f(id); + let items = self.tcx.hir_module_items(id); + queue.extend(items.submodules.iter().copied()) + } + } + + #[cfg(not(parallel_compiler))] + #[inline] + pub fn par_for_each_module(&self, f: impl Fn(LocalDefId)) { + self.for_each_module(f) + } + + #[cfg(parallel_compiler)] + pub fn par_for_each_module(&self, f: impl Fn(LocalDefId) + Sync) { + use rustc_data_structures::sync::{par_iter, ParallelIterator}; + par_iter_submodules(self.tcx, CRATE_DEF_ID, &f); + + fn par_iter_submodules<F>(tcx: TyCtxt<'_>, module: LocalDefId, f: &F) + where + F: Fn(LocalDefId) + Sync, + { + (*f)(module); + let items = tcx.hir_module_items(module); + par_iter(&items.submodules[..]).for_each(|&sm| par_iter_submodules(tcx, sm, f)); + } + } + /// Returns an iterator for the nodes in the ancestor tree of the `current_id` /// until the crate root is reached. Prefer this over your own loop using `get_parent_node`. pub fn parent_iter(&self, current_id: HirId) -> ParentHirIterator<'_, 'hir> { @@ -1118,3 +1146,69 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId) -> String { None => format!("unknown node{}", id_str), } } + +pub(super) fn hir_module_items(tcx: TyCtxt<'_>, module_id: LocalDefId) -> ModuleItems { + let mut collector = ModuleCollector { + tcx, + submodules: Vec::default(), + items: Vec::default(), + trait_items: Vec::default(), + impl_items: Vec::default(), + foreign_items: Vec::default(), + }; + + let (hir_mod, span, hir_id) = tcx.hir().get_module(module_id); + collector.visit_mod(hir_mod, span, hir_id); + + let ModuleCollector { submodules, items, trait_items, impl_items, foreign_items, .. } = + collector; + return ModuleItems { + submodules: submodules.into_boxed_slice(), + items: items.into_boxed_slice(), + trait_items: trait_items.into_boxed_slice(), + impl_items: impl_items.into_boxed_slice(), + foreign_items: foreign_items.into_boxed_slice(), + }; + + struct ModuleCollector<'tcx> { + tcx: TyCtxt<'tcx>, + submodules: Vec<LocalDefId>, + items: Vec<ItemId>, + trait_items: Vec<TraitItemId>, + impl_items: Vec<ImplItemId>, + foreign_items: Vec<ForeignItemId>, + } + + impl<'hir> Visitor<'hir> for ModuleCollector<'hir> { + type Map = Map<'hir>; + + fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> { + intravisit::NestedVisitorMap::All(self.tcx.hir()) + } + + fn visit_item(&mut self, item: &'hir Item<'hir>) { + self.items.push(item.item_id()); + if let ItemKind::Mod(..) = item.kind { + // If this declares another module, do not recurse inside it. + self.submodules.push(item.def_id); + } else { + intravisit::walk_item(self, item) + } + } + + fn visit_trait_item(&mut self, item: &'hir TraitItem<'hir>) { + self.trait_items.push(item.trait_item_id()); + intravisit::walk_trait_item(self, item) + } + + fn visit_impl_item(&mut self, item: &'hir ImplItem<'hir>) { + self.impl_items.push(item.impl_item_id()); + intravisit::walk_impl_item(self, item) + } + + fn visit_foreign_item(&mut self, item: &'hir ForeignItem<'hir>) { + self.foreign_items.push(item.foreign_item_id()); + intravisit::walk_foreign_item(self, item) + } + } +} diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index c8ea7454f0b..de4b75f9463 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -121,6 +121,17 @@ impl<'tcx> AttributeMap<'tcx> { } } +/// Gather the LocalDefId for each item-like within a module, including items contained within +/// bodies. The Ids are in visitor order. This is used to partition a pass between modules. +#[derive(Debug, HashStable)] +pub struct ModuleItems { + submodules: Box<[LocalDefId]>, + items: Box<[ItemId]>, + trait_items: Box<[TraitItemId]>, + impl_items: Box<[ImplItemId]>, + foreign_items: Box<[ForeignItemId]>, +} + impl<'tcx> TyCtxt<'tcx> { #[inline(always)] pub fn hir(self) -> map::Map<'tcx> { @@ -140,7 +151,7 @@ pub fn provide(providers: &mut Providers) { providers.hir_crate = |tcx, ()| tcx.untracked_crate; providers.index_hir = map::index_hir; providers.crate_hash = map::crate_hash; - providers.hir_module_items = |tcx, id| &tcx.untracked_crate.modules[&id]; + providers.hir_module_items = map::hir_module_items; providers.hir_owner = |tcx, id| { let owner = tcx.index_hir(()).map[id].as_ref()?; let node = owner.nodes[ItemLocalId::new(0)].as_ref().unwrap().node; diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 94267ec64c7..02f0294c8ad 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -33,6 +33,7 @@ #![feature(discriminant_kind)] #![feature(exhaustive_patterns)] #![feature(if_let_guard)] +#![feature(map_first_last)] #![feature(never_type)] #![feature(extern_types)] #![feature(new_uninit)] diff --git a/compiler/rustc_middle/src/middle/cstore.rs b/compiler/rustc_middle/src/middle/cstore.rs index 8150e679295..81c44b27033 100644 --- a/compiler/rustc_middle/src/middle/cstore.rs +++ b/compiler/rustc_middle/src/middle/cstore.rs @@ -199,14 +199,10 @@ pub trait CrateStore: std::fmt::Debug { // incr. comp. uses to identify a CrateNum. fn crate_name(&self, cnum: CrateNum) -> Symbol; fn stable_crate_id(&self, cnum: CrateNum) -> StableCrateId; + fn stable_crate_id_to_crate_num(&self, stable_crate_id: StableCrateId) -> CrateNum; /// Fetch a DefId from a DefPathHash for a foreign crate. - fn def_path_hash_to_def_id( - &self, - cnum: CrateNum, - index_guess: u32, - hash: DefPathHash, - ) -> Option<DefId>; + fn def_path_hash_to_def_id(&self, cnum: CrateNum, hash: DefPathHash) -> DefId; fn expn_hash_to_expn_id(&self, cnum: CrateNum, index_guess: u32, hash: ExpnHash) -> ExpnId; // utility functions diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index e8d30034dc4..3e9c02ee268 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -992,6 +992,9 @@ pub enum LocalInfo<'tcx> { StaticRef { def_id: DefId, is_thread_local: bool }, /// A temporary created that references the const with the given `DefId` ConstRef { def_id: DefId }, + /// A temporary created during the creation of an aggregate + /// (e.g. a temporary for `foo` in `MyStruct { my_field: foo }`) + AggregateTemp, } impl<'tcx> LocalDecl<'tcx> { diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index 567f65e83d9..b003a504691 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -332,17 +332,15 @@ pub enum ConstraintCategory { CopyBound, SizedBound, Assignment, + /// A constraint that came from a usage of a variable (e.g. in an ADT expression + /// like `Foo { field: my_val }`) + Usage, OpaqueType, ClosureUpvar(hir::HirId), /// A "boring" constraint (caused by the given location) is one that /// the user probably doesn't want to see described in diagnostics, /// because it is kind of an artifact of the type system setup. - /// Example: `x = Foo { field: y }` technically creates - /// intermediate regions representing the "type of `Foo { field: y - /// }`", and data flows from `y` into those variables, but they - /// are not very interesting. The assignment into `x` on the other - /// hand might be. Boring, // Boring and applicable everywhere. BoringNoLocation, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 4296acce1ff..c13d7720e37 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -52,8 +52,8 @@ rustc_queries! { /// /// This can be conveniently accessed by `tcx.hir().visit_item_likes_in_module`. /// Avoid calling this query directly. - query hir_module_items(key: LocalDefId) -> &'tcx hir::ModuleItems { - eval_always + query hir_module_items(key: LocalDefId) -> rustc_middle::hir::ModuleItems { + storage(ArenaCacheSelector<'tcx>) desc { |tcx| "HIR module items in `{}`", tcx.def_path_str(key.to_def_id()) } } @@ -1128,6 +1128,27 @@ rustc_queries! { desc { "computing layout of `{}`", key.value } } + /// Compute a `FnAbi` suitable for indirect calls, i.e. to `fn` pointers. + /// + /// NB: this doesn't handle virtual calls - those should use `fn_abi_of_instance` + /// instead, where the instance is an `InstanceDef::Virtual`. + query fn_abi_of_fn_ptr( + key: ty::ParamEnvAnd<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'tcx>>)> + ) -> Result<&'tcx abi::call::FnAbi<'tcx, Ty<'tcx>>, ty::layout::FnAbiError<'tcx>> { + desc { "computing call ABI of `{}` function pointers", key.value.0 } + } + + /// Compute a `FnAbi` suitable for declaring/defining an `fn` instance, and for + /// direct calls to an `fn`. + /// + /// NB: that includes virtual calls, which are represented by "direct calls" + /// to an `InstanceDef::Virtual` instance (of `<dyn Trait as Trait>::fn`). + query fn_abi_of_instance( + key: ty::ParamEnvAnd<'tcx, (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>)> + ) -> Result<&'tcx abi::call::FnAbi<'tcx, Ty<'tcx>>, ty::layout::FnAbiError<'tcx>> { + desc { "computing call ABI of `{}`", key.value.0 } + } + query dylib_dependency_formats(_: CrateNum) -> &'tcx [(CrateNum, LinkagePreference)] { desc { "dylib dependency formats of crate" } diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index b4ae56adf32..88a7722c9cc 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -349,7 +349,7 @@ pub enum ObligationCauseCode<'tcx> { WellFormed(Option<WellFormedLoc>), /// From `match_impl`. The cause for us having to match an impl, and the DefId we are matching against. - MatchImpl(Lrc<ObligationCauseCode<'tcx>>, DefId), + MatchImpl(ObligationCause<'tcx>, DefId), } /// The 'location' at which we try to perform HIR-based wf checking. diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 1f5057d1da2..72b8d7cce71 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1,7 +1,7 @@ //! Type context book-keeping. use crate::arena::Arena; -use crate::dep_graph::{DepGraph, DepNode}; +use crate::dep_graph::DepGraph; use crate::hir::place::Place as HirPlace; use crate::ich::{NodeIdHashingMode, StableHashingContext}; use crate::infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarInfos}; @@ -83,23 +83,7 @@ pub trait OnDiskCache<'tcx>: rustc_data_structures::sync::Sync { /// Converts a `DefPathHash` to its corresponding `DefId` in the current compilation /// session, if it still exists. This is used during incremental compilation to /// turn a deserialized `DefPathHash` into its current `DefId`. - fn def_path_hash_to_def_id( - &self, - tcx: TyCtxt<'tcx>, - def_path_hash: DefPathHash, - ) -> Option<DefId>; - - /// If the given `dep_node`'s hash still exists in the current compilation, - /// and its current `DefId` is foreign, calls `store_foreign_def_id` with it. - /// - /// Normally, `store_foreign_def_id_hash` can be called directly by - /// the dependency graph when we construct a `DepNode`. However, - /// when we re-use a deserialized `DepNode` from the previous compilation - /// session, we only have the `DefPathHash` available. This method is used - /// to that any `DepNode` that we re-use has a `DefPathHash` -> `RawId` written - /// out for usage in the next compilation session. - fn register_reused_dep_node(&self, tcx: TyCtxt<'tcx>, dep_node: &DepNode); - fn store_foreign_def_id_hash(&self, def_id: DefId, hash: DefPathHash); + fn def_path_hash_to_def_id(&self, tcx: TyCtxt<'tcx>, def_path_hash: DefPathHash) -> DefId; fn drop_serialized_data(&self, tcx: TyCtxt<'tcx>); @@ -118,8 +102,8 @@ pub struct CtxtInterners<'tcx> { /// The arena that types, regions, etc. are allocated from. arena: &'tcx WorkerLocal<Arena<'tcx>>, - /// Specifically use a speedy hash algorithm for these hash sets, since - /// they're accessed quite often. + // Specifically use a speedy hash algorithm for these hash sets, since + // they're accessed quite often. type_: InternedSet<'tcx, TyS<'tcx>>, type_list: InternedSet<'tcx, List<Ty<'tcx>>>, substs: InternedSet<'tcx, InternalSubsts<'tcx>>, @@ -132,9 +116,9 @@ pub struct CtxtInterners<'tcx> { projs: InternedSet<'tcx, List<ProjectionKind>>, place_elems: InternedSet<'tcx, List<PlaceElem<'tcx>>>, const_: InternedSet<'tcx, Const<'tcx>>, - /// Const allocations. - allocation: InternedSet<'tcx, Allocation>, + const_allocation: InternedSet<'tcx, Allocation>, bound_variable_kinds: InternedSet<'tcx, List<ty::BoundVariableKind>>, + layout: InternedSet<'tcx, Layout>, } impl<'tcx> CtxtInterners<'tcx> { @@ -152,8 +136,9 @@ impl<'tcx> CtxtInterners<'tcx> { projs: Default::default(), place_elems: Default::default(), const_: Default::default(), - allocation: Default::default(), + const_allocation: Default::default(), bound_variable_kinds: Default::default(), + layout: Default::default(), } } @@ -1062,10 +1047,9 @@ pub struct GlobalCtxt<'tcx> { /// Stores memory for globals (statics/consts). pub(crate) alloc_map: Lock<interpret::AllocMap<'tcx>>, - layout_interner: ShardedHashMap<&'tcx Layout, ()>, - output_filenames: Arc<OutputFilenames>, + // FIXME(eddyb) this doesn't belong here and should be using a query. pub(super) vtables_cache: Lock<FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), AllocId>>, } @@ -1107,13 +1091,6 @@ impl<'tcx> TyCtxt<'tcx> { self.arena.alloc(ty::AdtDef::new(self, did, kind, variants, repr)) } - pub fn intern_const_alloc(self, alloc: Allocation) -> &'tcx Allocation { - self.interners - .allocation - .intern(alloc, |alloc| Interned(self.interners.arena.alloc(alloc))) - .0 - } - /// Allocates a read-only byte or string literal for `mir::interpret`. pub fn allocate_bytes(self, bytes: &[u8]) -> interpret::AllocId { // Create an allocation that just contains these bytes. @@ -1122,20 +1099,19 @@ impl<'tcx> TyCtxt<'tcx> { self.create_memory_alloc(alloc) } + // FIXME(eddyb) move to `direct_interners!`. pub fn intern_stability(self, stab: attr::Stability) -> &'tcx attr::Stability { self.stability_interner.intern(stab, |stab| self.arena.alloc(stab)) } + // FIXME(eddyb) move to `direct_interners!`. pub fn intern_const_stability(self, stab: attr::ConstStability) -> &'tcx attr::ConstStability { self.const_stability_interner.intern(stab, |stab| self.arena.alloc(stab)) } - pub fn intern_layout(self, layout: Layout) -> &'tcx Layout { - self.layout_interner.intern(layout, |layout| self.arena.alloc(layout)) - } - /// Returns a range of the start/end indices specified with the /// `rustc_layout_scalar_valid_range` attribute. + // FIXME(eddyb) this is an awkward spot for this method, maybe move it? pub fn layout_scalar_valid_range(self, def_id: DefId) -> (Bound<u128>, Bound<u128>) { let attrs = self.get_attrs(def_id); let get = |name| { @@ -1210,7 +1186,6 @@ impl<'tcx> TyCtxt<'tcx> { evaluation_cache: Default::default(), crate_name: Symbol::intern(crate_name), data_layout, - layout_interner: Default::default(), stability_interner: Default::default(), const_stability_interner: Default::default(), alloc_map: Lock::new(interpret::AllocMap::new()), @@ -1316,6 +1291,17 @@ impl<'tcx> TyCtxt<'tcx> { } } + /// Maps a StableCrateId to the corresponding CrateNum. This method assumes + /// that the crate in question has already been loaded by the CrateStore. + #[inline] + pub fn stable_crate_id_to_crate_num(self, stable_crate_id: StableCrateId) -> CrateNum { + if stable_crate_id == self.sess.local_stable_crate_id() { + LOCAL_CRATE + } else { + self.untracked_resolutions.cstore.stable_crate_id_to_crate_num(stable_crate_id) + } + } + pub fn def_path_debug_str(self, def_id: DefId) -> String { // We are explicitly not going through queries here in order to get // crate name and stable crate id since this code is called from debug!() @@ -1670,7 +1656,7 @@ macro_rules! nop_list_lift { nop_lift! {type_; Ty<'a> => Ty<'tcx>} nop_lift! {region; Region<'a> => Region<'tcx>} nop_lift! {const_; &'a Const<'a> => &'tcx Const<'tcx>} -nop_lift! {allocation; &'a Allocation => &'tcx Allocation} +nop_lift! {const_allocation; &'a Allocation => &'tcx Allocation} nop_lift! {predicate; &'a PredicateInner<'a> => &'tcx PredicateInner<'tcx>} nop_list_lift! {type_list; Ty<'a> => Ty<'tcx>} @@ -1962,8 +1948,12 @@ impl<'tcx> TyCtxt<'tcx> { "Const Stability interner: #{}", self.0.const_stability_interner.len() )?; - writeln!(fmt, "Allocation interner: #{}", self.0.interners.allocation.len())?; - writeln!(fmt, "Layout interner: #{}", self.0.layout_interner.len())?; + writeln!( + fmt, + "Const Allocation interner: #{}", + self.0.interners.const_allocation.len() + )?; + writeln!(fmt, "Layout interner: #{}", self.0.interners.layout.len())?; Ok(()) } @@ -2051,38 +2041,6 @@ impl<'tcx, T> Borrow<[T]> for Interned<'tcx, List<T>> { } } -impl<'tcx> Borrow<RegionKind> for Interned<'tcx, RegionKind> { - fn borrow(&self) -> &RegionKind { - &self.0 - } -} - -impl<'tcx> Borrow<Const<'tcx>> for Interned<'tcx, Const<'tcx>> { - fn borrow<'a>(&'a self) -> &'a Const<'tcx> { - &self.0 - } -} - -impl<'tcx> Borrow<Allocation> for Interned<'tcx, Allocation> { - fn borrow<'a>(&'a self) -> &'a Allocation { - &self.0 - } -} - -impl<'tcx> PartialEq for Interned<'tcx, Allocation> { - fn eq(&self, other: &Self) -> bool { - self.0 == other.0 - } -} - -impl<'tcx> Eq for Interned<'tcx, Allocation> {} - -impl<'tcx> Hash for Interned<'tcx, Allocation> { - fn hash<H: Hasher>(&self, s: &mut H) { - self.0.hash(s) - } -} - macro_rules! direct_interners { ($($name:ident: $method:ident($ty:ty),)+) => { $(impl<'tcx> PartialEq for Interned<'tcx, $ty> { @@ -2099,9 +2057,15 @@ macro_rules! direct_interners { } } + impl<'tcx> Borrow<$ty> for Interned<'tcx, $ty> { + fn borrow<'a>(&'a self) -> &'a $ty { + &self.0 + } + } + impl<'tcx> TyCtxt<'tcx> { pub fn $method(self, v: $ty) -> &'tcx $ty { - self.interners.$name.intern_ref(&v, || { + self.interners.$name.intern(v, |v| { Interned(self.interners.arena.alloc(v)) }).0 } @@ -2112,6 +2076,8 @@ macro_rules! direct_interners { direct_interners! { region: mk_region(RegionKind), const_: mk_const(Const<'tcx>), + const_allocation: intern_const_alloc(Allocation), + layout: intern_layout(Layout), } macro_rules! slice_interners { diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 1bea1cbc3b9..cfbbec374a1 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -1,4 +1,3 @@ -use crate::ich::StableHashingContext; use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; use crate::mir::{GeneratorLayout, GeneratorSavedLocal}; use crate::ty::subst::Subst; @@ -6,7 +5,6 @@ use crate::ty::{self, subst::SubstsRef, ReprOptions, Ty, TyCtxt, TypeFoldable}; use rustc_ast as ast; use rustc_attr as attr; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_hir as hir; use rustc_hir::lang_items::LangItem; use rustc_index::bit_set::BitSet; @@ -18,15 +16,19 @@ use rustc_target::abi::call::{ ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, Conv, FnAbi, PassMode, Reg, RegKind, }; use rustc_target::abi::*; -use rustc_target::spec::{abi::Abi as SpecAbi, HasTargetSpec, PanicStrategy}; +use rustc_target::spec::{abi::Abi as SpecAbi, HasTargetSpec, PanicStrategy, Target}; use std::cmp; use std::fmt; use std::iter; -use std::mem; use std::num::NonZeroUsize; use std::ops::Bound; +pub fn provide(providers: &mut ty::query::Providers) { + *providers = + ty::query::Providers { layout_of, fn_abi_of_fn_ptr, fn_abi_of_instance, ..*providers }; +} + pub trait IntegerExt { fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>, signed: bool) -> Ty<'tcx>; fn from_attr<C: HasDataLayout>(cx: &C, ity: attr::IntType) -> Integer; @@ -191,7 +193,7 @@ pub const FAT_PTR_EXTRA: usize = 1; /// * Cranelift stores the base-2 log of the lane count in a 4 bit integer. pub const MAX_SIMD_LANES: u64 = 1 << 0xF; -#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable)] +#[derive(Copy, Clone, Debug, HashStable, TyEncodable, TyDecodable)] pub enum LayoutError<'tcx> { Unknown(Ty<'tcx>), SizeOverflow(Ty<'tcx>), @@ -248,10 +250,6 @@ fn layout_of<'tcx>( }) } -pub fn provide(providers: &mut ty::query::Providers) { - *providers = ty::query::Providers { layout_of, ..*providers }; -} - pub struct LayoutCx<'tcx, C> { pub tcx: C, pub param_env: ty::ParamEnv<'tcx>, @@ -2015,6 +2013,12 @@ impl<'tcx> HasDataLayout for TyCtxt<'tcx> { } } +impl<'tcx> HasTargetSpec for TyCtxt<'tcx> { + fn target_spec(&self) -> &Target { + &self.sess.target + } +} + impl<'tcx> HasTyCtxt<'tcx> for TyCtxt<'tcx> { #[inline] fn tcx(&self) -> TyCtxt<'tcx> { @@ -2029,6 +2033,12 @@ impl<'tcx> HasDataLayout for ty::query::TyCtxtAt<'tcx> { } } +impl<'tcx> HasTargetSpec for ty::query::TyCtxtAt<'tcx> { + fn target_spec(&self) -> &Target { + &self.sess.target + } +} + impl<'tcx> HasTyCtxt<'tcx> for ty::query::TyCtxtAt<'tcx> { #[inline] fn tcx(&self) -> TyCtxt<'tcx> { @@ -2048,6 +2058,12 @@ impl<'tcx, T: HasDataLayout> HasDataLayout for LayoutCx<'tcx, T> { } } +impl<'tcx, T: HasTargetSpec> HasTargetSpec for LayoutCx<'tcx, T> { + fn target_spec(&self) -> &Target { + self.tcx.target_spec() + } +} + impl<'tcx, T: HasTyCtxt<'tcx>> HasTyCtxt<'tcx> for LayoutCx<'tcx, T> { fn tcx(&self) -> TyCtxt<'tcx> { self.tcx.tcx() @@ -2130,10 +2146,10 @@ pub trait LayoutOf<'tcx>: LayoutOfHelpers<'tcx> { #[inline] fn spanned_layout_of(&self, ty: Ty<'tcx>, span: Span) -> Self::LayoutOfResult { let span = if !span.is_dummy() { span } else { self.layout_tcx_at_span() }; + let tcx = self.tcx().at(span); + MaybeResult::from( - self.tcx() - .at(span) - .layout_of(self.param_env().and(ty)) + tcx.layout_of(self.param_env().and(ty)) .map_err(|err| self.handle_layout_err(err, span, ty)), ) } @@ -2519,24 +2535,12 @@ where } } -impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for LayoutError<'tcx> { - #[inline] - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - use crate::ty::layout::LayoutError::*; - mem::discriminant(self).hash_stable(hcx, hasher); - - match *self { - Unknown(t) | SizeOverflow(t) => t.hash_stable(hcx, hasher), - } - } -} - impl<'tcx> ty::Instance<'tcx> { // NOTE(eddyb) this is private to avoid using it from outside of - // `FnAbi::of_instance` - any other uses are either too high-level + // `fn_abi_of_instance` - any other uses are either too high-level // for `Instance` (e.g. typeck would use `Ty::fn_sig` instead), // or should go through `FnAbi` instead, to avoid losing any - // adjustments `FnAbi::of_instance` might be performing. + // adjustments `fn_abi_of_instance` might be performing. fn fn_sig_for_fn_abi(&self, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> { // FIXME(davidtwco,eddyb): A `ParamEnv` should be passed through to this function. let ty = self.ty(tcx, ty::ParamEnv::reveal_all()); @@ -2633,34 +2637,6 @@ impl<'tcx> ty::Instance<'tcx> { } } -pub trait FnAbiExt<'tcx, C> -where - C: LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>> + HasTargetSpec, -{ - /// Compute a `FnAbi` suitable for indirect calls, i.e. to `fn` pointers. - /// - /// NB: this doesn't handle virtual calls - those should use `FnAbi::of_instance` - /// instead, where the instance is an `InstanceDef::Virtual`. - fn of_fn_ptr(cx: &C, sig: ty::PolyFnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self; - - /// Compute a `FnAbi` suitable for declaring/defining an `fn` instance, and for - /// direct calls to an `fn`. - /// - /// NB: that includes virtual calls, which are represented by "direct calls" - /// to an `InstanceDef::Virtual` instance (of `<dyn Trait as Trait>::fn`). - fn of_instance(cx: &C, instance: ty::Instance<'tcx>, extra_args: &[Ty<'tcx>]) -> Self; - - fn new_internal( - cx: &C, - sig: ty::PolyFnSig<'tcx>, - extra_args: &[Ty<'tcx>], - caller_location: Option<Ty<'tcx>>, - codegen_fn_attr_flags: CodegenFnAttrFlags, - make_self_ptr_thin: bool, - ) -> Self; - fn adjust_for_abi(&mut self, cx: &C, abi: SpecAbi); -} - /// Calculates whether a function's ABI can unwind or not. /// /// This takes two primary parameters: @@ -2816,48 +2792,175 @@ pub fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: SpecAbi) -> Conv { } } -impl<'tcx, C> FnAbiExt<'tcx, C> for call::FnAbi<'tcx, Ty<'tcx>> -where - C: LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>> + HasTargetSpec, -{ - fn of_fn_ptr(cx: &C, sig: ty::PolyFnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self { - call::FnAbi::new_internal(cx, sig, extra_args, None, CodegenFnAttrFlags::empty(), false) +/// Error produced by attempting to compute or adjust a `FnAbi`. +#[derive(Clone, Debug, HashStable)] +pub enum FnAbiError<'tcx> { + /// Error produced by a `layout_of` call, while computing `FnAbi` initially. + Layout(LayoutError<'tcx>), + + /// Error produced by attempting to adjust a `FnAbi`, for a "foreign" ABI. + AdjustForForeignAbi(call::AdjustForForeignAbiError), +} + +impl From<LayoutError<'tcx>> for FnAbiError<'tcx> { + fn from(err: LayoutError<'tcx>) -> Self { + Self::Layout(err) } +} - fn of_instance(cx: &C, instance: ty::Instance<'tcx>, extra_args: &[Ty<'tcx>]) -> Self { - let sig = instance.fn_sig_for_fn_abi(cx.tcx()); +impl From<call::AdjustForForeignAbiError> for FnAbiError<'_> { + fn from(err: call::AdjustForForeignAbiError) -> Self { + Self::AdjustForForeignAbi(err) + } +} - let caller_location = if instance.def.requires_caller_location(cx.tcx()) { - Some(cx.tcx().caller_location_ty()) - } else { - None - }; +impl<'tcx> fmt::Display for FnAbiError<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Layout(err) => err.fmt(f), + Self::AdjustForForeignAbi(err) => err.fmt(f), + } + } +} + +// FIXME(eddyb) maybe use something like this for an unified `fn_abi_of`, not +// just for error handling. +#[derive(Debug)] +pub enum FnAbiRequest<'tcx> { + OfFnPtr { sig: ty::PolyFnSig<'tcx>, extra_args: &'tcx ty::List<Ty<'tcx>> }, + OfInstance { instance: ty::Instance<'tcx>, extra_args: &'tcx ty::List<Ty<'tcx>> }, +} + +/// Trait for contexts that want to be able to compute `FnAbi`s. +/// This automatically gives access to `FnAbiOf`, through a blanket `impl`. +pub trait FnAbiOfHelpers<'tcx>: LayoutOfHelpers<'tcx> { + /// The `&FnAbi`-wrapping type (or `&FnAbi` itself), which will be + /// returned from `fn_abi_of_*` (see also `handle_fn_abi_err`). + type FnAbiOfResult: MaybeResult<&'tcx FnAbi<'tcx, Ty<'tcx>>>; - let attrs = cx.tcx().codegen_fn_attrs(instance.def_id()).flags; + /// Helper used for `fn_abi_of_*`, to adapt `tcx.fn_abi_of_*(...)` into a + /// `Self::FnAbiOfResult` (which does not need to be a `Result<...>`). + /// + /// Most `impl`s, which propagate `FnAbiError`s, should simply return `err`, + /// but this hook allows e.g. codegen to return only `&FnAbi` from its + /// `cx.fn_abi_of_*(...)`, without any `Result<...>` around it to deal with + /// (and any `FnAbiError`s are turned into fatal errors or ICEs). + fn handle_fn_abi_err( + &self, + err: FnAbiError<'tcx>, + span: Span, + fn_abi_request: FnAbiRequest<'tcx>, + ) -> <Self::FnAbiOfResult as MaybeResult<&'tcx FnAbi<'tcx, Ty<'tcx>>>>::Error; +} + +/// Blanket extension trait for contexts that can compute `FnAbi`s. +pub trait FnAbiOf<'tcx>: FnAbiOfHelpers<'tcx> { + /// Compute a `FnAbi` suitable for indirect calls, i.e. to `fn` pointers. + /// + /// NB: this doesn't handle virtual calls - those should use `fn_abi_of_instance` + /// instead, where the instance is an `InstanceDef::Virtual`. + #[inline] + fn fn_abi_of_fn_ptr( + &self, + sig: ty::PolyFnSig<'tcx>, + extra_args: &'tcx ty::List<Ty<'tcx>>, + ) -> Self::FnAbiOfResult { + // FIXME(eddyb) get a better `span` here. + let span = self.layout_tcx_at_span(); + let tcx = self.tcx().at(span); + + MaybeResult::from(tcx.fn_abi_of_fn_ptr(self.param_env().and((sig, extra_args))).map_err( + |err| self.handle_fn_abi_err(err, span, FnAbiRequest::OfFnPtr { sig, extra_args }), + )) + } - call::FnAbi::new_internal( - cx, - sig, - extra_args, - caller_location, - attrs, - matches!(instance.def, ty::InstanceDef::Virtual(..)), + /// Compute a `FnAbi` suitable for declaring/defining an `fn` instance, and for + /// direct calls to an `fn`. + /// + /// NB: that includes virtual calls, which are represented by "direct calls" + /// to an `InstanceDef::Virtual` instance (of `<dyn Trait as Trait>::fn`). + #[inline] + fn fn_abi_of_instance( + &self, + instance: ty::Instance<'tcx>, + extra_args: &'tcx ty::List<Ty<'tcx>>, + ) -> Self::FnAbiOfResult { + // FIXME(eddyb) get a better `span` here. + let span = self.layout_tcx_at_span(); + let tcx = self.tcx().at(span); + + MaybeResult::from( + tcx.fn_abi_of_instance(self.param_env().and((instance, extra_args))).map_err(|err| { + // HACK(eddyb) at least for definitions of/calls to `Instance`s, + // we can get some kind of span even if one wasn't provided. + // However, we don't do this early in order to avoid calling + // `def_span` unconditionally (which may have a perf penalty). + let span = if !span.is_dummy() { span } else { tcx.def_span(instance.def_id()) }; + self.handle_fn_abi_err(err, span, FnAbiRequest::OfInstance { instance, extra_args }) + }), ) } +} - fn new_internal( - cx: &C, +impl<C: FnAbiOfHelpers<'tcx>> FnAbiOf<'tcx> for C {} + +fn fn_abi_of_fn_ptr<'tcx>( + tcx: TyCtxt<'tcx>, + query: ty::ParamEnvAnd<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'tcx>>)>, +) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, FnAbiError<'tcx>> { + let (param_env, (sig, extra_args)) = query.into_parts(); + + LayoutCx { tcx, param_env }.fn_abi_new_uncached( + sig, + extra_args, + None, + CodegenFnAttrFlags::empty(), + false, + ) +} + +fn fn_abi_of_instance<'tcx>( + tcx: TyCtxt<'tcx>, + query: ty::ParamEnvAnd<'tcx, (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>)>, +) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, FnAbiError<'tcx>> { + let (param_env, (instance, extra_args)) = query.into_parts(); + + let sig = instance.fn_sig_for_fn_abi(tcx); + + let caller_location = if instance.def.requires_caller_location(tcx) { + Some(tcx.caller_location_ty()) + } else { + None + }; + + let attrs = tcx.codegen_fn_attrs(instance.def_id()).flags; + + LayoutCx { tcx, param_env }.fn_abi_new_uncached( + sig, + extra_args, + caller_location, + attrs, + matches!(instance.def, ty::InstanceDef::Virtual(..)), + ) +} + +impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { + // FIXME(eddyb) perhaps group the signature/type-containing (or all of them?) + // arguments of this method, into a separate `struct`. + fn fn_abi_new_uncached( + &self, sig: ty::PolyFnSig<'tcx>, extra_args: &[Ty<'tcx>], caller_location: Option<Ty<'tcx>>, codegen_fn_attr_flags: CodegenFnAttrFlags, + // FIXME(eddyb) replace this with something typed, like an `enum`. force_thin_self_ptr: bool, - ) -> Self { - debug!("FnAbi::new_internal({:?}, {:?})", sig, extra_args); + ) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, FnAbiError<'tcx>> { + debug!("fn_abi_new_uncached({:?}, {:?})", sig, extra_args); - let sig = cx.tcx().normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), sig); + let sig = self.tcx.normalize_erasing_late_bound_regions(self.param_env, sig); - let conv = conv_from_spec_abi(cx.tcx(), sig.abi); + let conv = conv_from_spec_abi(self.tcx(), sig.abi); let mut inputs = sig.inputs(); let extra_args = if sig.abi == RustCall { @@ -2884,7 +2987,7 @@ where extra_args.to_vec() }; - let target = &cx.tcx().sess.target; + let target = &self.tcx.sess.target; let target_env_gnu_like = matches!(&target.env[..], "gnu" | "musl"); let win_x64_gnu = target.os == "windows" && target.arch == "x86_64" && target.env == "gnu"; let linux_s390x_gnu_like = @@ -2917,7 +3020,7 @@ where attrs.set(ArgAttribute::NonNull); } - if let Some(pointee) = layout.pointee_info_at(cx, offset) { + if let Some(pointee) = layout.pointee_info_at(self, offset) { if let Some(kind) = pointee.safe { attrs.pointee_align = Some(pointee.align); @@ -2961,20 +3064,20 @@ where } }; - let arg_of = |ty: Ty<'tcx>, arg_idx: Option<usize>| { + let arg_of = |ty: Ty<'tcx>, arg_idx: Option<usize>| -> Result<_, FnAbiError<'tcx>> { let is_return = arg_idx.is_none(); - let layout = cx.layout_of(ty); + let layout = self.layout_of(ty)?; let layout = if force_thin_self_ptr && arg_idx == Some(0) { // Don't pass the vtable, it's not an argument of the virtual fn. // Instead, pass just the data pointer, but give it the type `*const/mut dyn Trait` // or `&/&mut dyn Trait` because this is special-cased elsewhere in codegen - make_thin_self_ptr(cx, layout) + make_thin_self_ptr(self, layout) } else { layout }; - let mut arg = ArgAbi::new(cx, layout, |layout, scalar, offset| { + let mut arg = ArgAbi::new(self, layout, |layout, scalar, offset| { let mut attrs = ArgAttributes::new(); adjust_for_rust_scalar(&mut attrs, scalar, *layout, offset, is_return); attrs @@ -2995,11 +3098,11 @@ where } } - arg + Ok(arg) }; let mut fn_abi = FnAbi { - ret: arg_of(sig.output(), None), + ret: arg_of(sig.output(), None)?, args: inputs .iter() .cloned() @@ -3007,20 +3110,24 @@ where .chain(caller_location) .enumerate() .map(|(i, ty)| arg_of(ty, Some(i))) - .collect(), + .collect::<Result<_, _>>()?, c_variadic: sig.c_variadic, fixed_count: inputs.len(), conv, - can_unwind: fn_can_unwind(cx.tcx(), codegen_fn_attr_flags, sig.abi), + can_unwind: fn_can_unwind(self.tcx(), codegen_fn_attr_flags, sig.abi), }; - fn_abi.adjust_for_abi(cx, sig.abi); - debug!("FnAbi::new_internal = {:?}", fn_abi); - fn_abi + self.fn_abi_adjust_for_abi(&mut fn_abi, sig.abi)?; + debug!("fn_abi_new_uncached = {:?}", fn_abi); + Ok(self.tcx.arena.alloc(fn_abi)) } - fn adjust_for_abi(&mut self, cx: &C, abi: SpecAbi) { + fn fn_abi_adjust_for_abi( + &self, + fn_abi: &mut FnAbi<'tcx, Ty<'tcx>>, + abi: SpecAbi, + ) -> Result<(), FnAbiError<'tcx>> { if abi == SpecAbi::Unadjusted { - return; + return Ok(()); } if abi == SpecAbi::Rust @@ -3057,7 +3164,7 @@ where // anyway, we control all calls to it in libstd. Abi::Vector { .. } if abi != SpecAbi::PlatformIntrinsic - && cx.tcx().sess.target.simd_types_indirect => + && self.tcx.sess.target.simd_types_indirect => { arg.make_indirect(); return; @@ -3068,7 +3175,7 @@ where // Pass and return structures up to 2 pointers in size by value, matching `ScalarPair`. // LLVM will usually pass these in 2 registers, which is more efficient than by-ref. - let max_by_val_size = Pointer.size(cx) * 2; + let max_by_val_size = Pointer.size(self) * 2; let size = arg.layout.size; if arg.layout.is_unsized() || size > max_by_val_size { @@ -3080,16 +3187,15 @@ where arg.cast_to(Reg { kind: RegKind::Integer, size }); } }; - fixup(&mut self.ret); - for arg in &mut self.args { + fixup(&mut fn_abi.ret); + for arg in &mut fn_abi.args { fixup(arg); } - return; + } else { + fn_abi.adjust_for_foreign_abi(self, abi)?; } - if let Err(msg) = self.adjust_for_cabi(cx, abi) { - cx.tcx().sess.fatal(&msg); - } + Ok(()) } } diff --git a/compiler/rustc_middle/src/ty/query.rs b/compiler/rustc_middle/src/ty/query.rs index 15a8888ee65..154b26464a8 100644 --- a/compiler/rustc_middle/src/ty/query.rs +++ b/compiler/rustc_middle/src/ty/query.rs @@ -48,6 +48,7 @@ use rustc_index::{bit_set::FiniteBitSet, vec::IndexVec}; use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion}; use rustc_session::utils::NativeLibKind; use rustc_session::Limits; +use rustc_target::abi; use rustc_target::spec::PanicStrategy; use rustc_ast as ast; diff --git a/compiler/rustc_mir_build/src/build/expr/as_operand.rs b/compiler/rustc_mir_build/src/build/expr/as_operand.rs index bbb2f89fda9..b627b0763a2 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_operand.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_operand.rs @@ -20,7 +20,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { expr: &Expr<'tcx>, ) -> BlockAnd<Operand<'tcx>> { let local_scope = self.local_scope(); - self.as_operand(block, Some(local_scope), expr) + self.as_operand(block, Some(local_scope), expr, None) } /// Returns an operand suitable for use until the end of the current scope expression and @@ -85,6 +85,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// temporary `tmp = x`, so that we capture the value of `x` at /// this time. /// + /// If we end up needing to create a temporary, then we will use + /// `local_info` as its `LocalInfo`, unless `as_temporary` + /// has already assigned it a non-`None` `LocalInfo`. + /// Normally, you should use `None` for `local_info` + /// /// The operand is known to be live until the end of `scope`. /// /// Like `as_local_call_operand`, except that the argument will @@ -94,15 +99,16 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { mut block: BasicBlock, scope: Option<region::Scope>, expr: &Expr<'tcx>, + local_info: Option<Box<LocalInfo<'tcx>>>, ) -> BlockAnd<Operand<'tcx>> { - debug!("as_operand(block={:?}, expr={:?})", block, expr); + debug!("as_operand(block={:?}, expr={:?} local_info={:?})", block, expr, local_info); let this = self; if let ExprKind::Scope { region_scope, lint_level, value } = expr.kind { let source_info = this.source_info(expr.span); let region_scope = (region_scope, source_info); return this.in_scope(region_scope, lint_level, |this| { - this.as_operand(block, scope, &this.thir[value]) + this.as_operand(block, scope, &this.thir[value], local_info) }); } @@ -115,6 +121,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } Category::Place | Category::Rvalue(..) => { let operand = unpack!(block = this.as_temp(block, scope, expr, Mutability::Mut)); + if this.local_decls[operand].local_info.is_none() { + this.local_decls[operand].local_info = local_info; + } block.and(Operand::Move(Place::from(operand))) } } @@ -167,6 +176,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - this.as_operand(block, scope, expr) + this.as_operand(block, scope, expr, None) } } diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs index be0d5d2f1b2..4b40faaf195 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs @@ -52,16 +52,16 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } ExprKind::Repeat { value, count } => { let value_operand = - unpack!(block = this.as_operand(block, scope, &this.thir[value])); + unpack!(block = this.as_operand(block, scope, &this.thir[value], None)); block.and(Rvalue::Repeat(value_operand, count)) } ExprKind::Binary { op, lhs, rhs } => { - let lhs = unpack!(block = this.as_operand(block, scope, &this.thir[lhs])); - let rhs = unpack!(block = this.as_operand(block, scope, &this.thir[rhs])); + let lhs = unpack!(block = this.as_operand(block, scope, &this.thir[lhs], None)); + let rhs = unpack!(block = this.as_operand(block, scope, &this.thir[rhs], None)); this.build_binary_op(block, op, expr_span, expr.ty, lhs, rhs) } ExprKind::Unary { op, arg } => { - let arg = unpack!(block = this.as_operand(block, scope, &this.thir[arg])); + let arg = unpack!(block = this.as_operand(block, scope, &this.thir[arg], None)); // Check for -MIN on signed integers if this.check_overflow && op == UnOp::Neg && expr.ty.is_signed() { let bool_ty = this.tcx.types.bool; @@ -116,11 +116,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block.and(Rvalue::Use(Operand::Move(Place::from(result)))) } ExprKind::Cast { source } => { - let source = unpack!(block = this.as_operand(block, scope, &this.thir[source])); + let source = + unpack!(block = this.as_operand(block, scope, &this.thir[source], None)); block.and(Rvalue::Cast(CastKind::Misc, source, expr.ty)) } ExprKind::Pointer { cast, source } => { - let source = unpack!(block = this.as_operand(block, scope, &this.thir[source])); + let source = + unpack!(block = this.as_operand(block, scope, &this.thir[source], None)); block.and(Rvalue::Cast(CastKind::Pointer(cast), source, expr.ty)) } ExprKind::Array { ref fields } => { @@ -155,7 +157,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let fields: Vec<_> = fields .into_iter() .copied() - .map(|f| unpack!(block = this.as_operand(block, scope, &this.thir[f]))) + .map(|f| unpack!(block = this.as_operand(block, scope, &this.thir[f], None))) .collect(); block.and(Rvalue::Aggregate(Box::new(AggregateKind::Array(el_ty)), fields)) @@ -166,7 +168,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let fields: Vec<_> = fields .into_iter() .copied() - .map(|f| unpack!(block = this.as_operand(block, scope, &this.thir[f]))) + .map(|f| unpack!(block = this.as_operand(block, scope, &this.thir[f], None))) .collect(); block.and(Rvalue::Aggregate(Box::new(AggregateKind::Tuple), fields)) @@ -242,7 +244,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { &this.thir[arg], ) ), - _ => unpack!(block = this.as_operand(block, scope, upvar)), + _ => { + unpack!(block = this.as_operand(block, scope, upvar, None)) + } } } } @@ -304,7 +308,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Category::of(&expr.kind), Some(Category::Rvalue(RvalueFunc::AsRvalue)) )); - let operand = unpack!(block = this.as_operand(block, scope, expr)); + let operand = unpack!(block = this.as_operand(block, scope, expr, None)); block.and(Rvalue::Use(operand)) } } diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index e30e758e637..1803a18441c 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -326,10 +326,16 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let fields_map: FxHashMap<_, _> = fields .into_iter() .map(|f| { + let local_info = Box::new(LocalInfo::AggregateTemp); ( f.name, unpack!( - block = this.as_operand(block, Some(scope), &this.thir[f.expr]) + block = this.as_operand( + block, + Some(scope), + &this.thir[f.expr], + Some(local_info) + ) ), ) }) @@ -508,7 +514,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ExprKind::Yield { value } => { let scope = this.local_scope(); - let value = unpack!(block = this.as_operand(block, Some(scope), &this.thir[value])); + let value = + unpack!(block = this.as_operand(block, Some(scope), &this.thir[value], None)); let resume = this.cfg.start_new_block(); this.cfg.terminate( block, diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs index e3cfd1d0afc..d6cd505cbb5 100644 --- a/compiler/rustc_mir_transform/src/simplify.rs +++ b/compiler/rustc_mir_transform/src/simplify.rs @@ -95,8 +95,6 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { pub fn simplify(mut self) { self.strip_nops(); - let mut start = START_BLOCK; - // Vec of the blocks that should be merged. We store the indices here, instead of the // statements itself to avoid moving the (relatively) large statements twice. // We do not push the statements directly into the target block (`bb`) as that is slower @@ -105,8 +103,6 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { loop { let mut changed = false; - self.collapse_goto_chain(&mut start, &mut changed); - for bb in self.basic_blocks.indices() { if self.pred_count[bb] == 0 { continue; @@ -149,27 +145,6 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { break; } } - - if start != START_BLOCK { - debug_assert!(self.pred_count[START_BLOCK] == 0); - self.basic_blocks.swap(START_BLOCK, start); - self.pred_count.swap(START_BLOCK, start); - - // pred_count == 1 if the start block has no predecessor _blocks_. - if self.pred_count[START_BLOCK] > 1 { - for (bb, data) in self.basic_blocks.iter_enumerated_mut() { - if self.pred_count[bb] == 0 { - continue; - } - - for target in data.terminator_mut().successors_mut() { - if *target == start { - *target = START_BLOCK; - } - } - } - } - } } /// This function will return `None` if diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs index 3c55a4b0a8f..0f768b7819b 100644 --- a/compiler/rustc_monomorphize/src/polymorphize.rs +++ b/compiler/rustc_monomorphize/src/polymorphize.rs @@ -30,7 +30,7 @@ pub fn provide(providers: &mut Providers) { /// Determine which generic parameters are used by the function/method/closure represented by /// `def_id`. Returns a bitset where bits representing unused parameters are set (`is_empty` /// indicates all parameters are used). -#[instrument(skip(tcx))] +#[instrument(level = "debug", skip(tcx))] fn unused_generic_params(tcx: TyCtxt<'_>, def_id: DefId) -> FiniteBitSet<u32> { if !tcx.sess.opts.debugging_opts.polymorphize { // If polymorphization disabled, then all parameters are used. @@ -100,7 +100,7 @@ fn unused_generic_params(tcx: TyCtxt<'_>, def_id: DefId) -> FiniteBitSet<u32> { /// Some parameters are considered used-by-default, such as non-generic parameters and the dummy /// generic parameters from closures, this function marks them as used. `leaf_is_closure` should /// be `true` if the item that `unused_generic_params` was invoked on is a closure. -#[instrument(skip(tcx, def_id, generics, unused_parameters))] +#[instrument(level = "debug", skip(tcx, def_id, generics, unused_parameters))] fn mark_used_by_default_parameters<'tcx>( tcx: TyCtxt<'tcx>, def_id: DefId, @@ -158,7 +158,7 @@ fn mark_used_by_default_parameters<'tcx>( /// Search the predicates on used generic parameters for any unused generic parameters, and mark /// those as used. -#[instrument(skip(tcx, def_id))] +#[instrument(level = "debug", skip(tcx, def_id))] fn mark_used_by_predicates<'tcx>( tcx: TyCtxt<'tcx>, def_id: DefId, @@ -196,7 +196,7 @@ fn mark_used_by_predicates<'tcx>( /// Emit errors for the function annotated by `#[rustc_polymorphize_error]`, labelling each generic /// parameter which was unused. -#[instrument(skip(tcx, generics))] +#[instrument(level = "debug", skip(tcx, generics))] fn emit_unused_generic_params_error<'tcx>( tcx: TyCtxt<'tcx>, def_id: DefId, @@ -241,7 +241,7 @@ struct MarkUsedGenericParams<'a, 'tcx> { impl<'a, 'tcx> MarkUsedGenericParams<'a, 'tcx> { /// Invoke `unused_generic_params` on a body contained within the current item (e.g. /// a closure, generator or constant). - #[instrument(skip(self, def_id, substs))] + #[instrument(level = "debug", skip(self, def_id, substs))] fn visit_child_body(&mut self, def_id: DefId, substs: SubstsRef<'tcx>) { let unused = self.tcx.unused_generic_params(def_id); debug!(?self.unused_parameters, ?unused); @@ -256,7 +256,7 @@ impl<'a, 'tcx> MarkUsedGenericParams<'a, 'tcx> { } impl<'a, 'tcx> Visitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> { - #[instrument(skip(self, local))] + #[instrument(level = "debug", skip(self, local))] fn visit_local_decl(&mut self, local: Local, local_decl: &LocalDecl<'tcx>) { if local == Local::from_usize(1) { let def_kind = self.tcx.def_kind(self.def_id); @@ -286,7 +286,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> { fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> { Some(self.tcx) } - #[instrument(skip(self))] + #[instrument(level = "debug", skip(self))] fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> ControlFlow<Self::BreakTy> { if !c.potentially_has_param_types_or_consts() { return ControlFlow::CONTINUE; @@ -319,7 +319,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> { } } - #[instrument(skip(self))] + #[instrument(level = "debug", skip(self))] fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { if !ty.potentially_has_param_types_or_consts() { return ControlFlow::CONTINUE; @@ -361,7 +361,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for HasUsedGenericParams<'a, 'tcx> { Some(self.tcx) } - #[instrument(skip(self))] + #[instrument(level = "debug", skip(self))] fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> ControlFlow<Self::BreakTy> { if !c.potentially_has_param_types_or_consts() { return ControlFlow::CONTINUE; @@ -379,7 +379,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for HasUsedGenericParams<'a, 'tcx> { } } - #[instrument(skip(self))] + #[instrument(level = "debug", skip(self))] fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { if !ty.potentially_has_param_types_or_consts() { return ControlFlow::CONTINUE; diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 4fccfc287fd..708df5e46d4 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -1334,30 +1334,25 @@ impl<'a> Parser<'a> { pub(super) fn recover_parens_around_for_head( &mut self, pat: P<Pat>, - expr: &Expr, begin_paren: Option<Span>, ) -> P<Pat> { match (&self.token.kind, begin_paren) { (token::CloseDelim(token::Paren), Some(begin_par_sp)) => { self.bump(); - let pat_str = self - // Remove the `(` from the span of the pattern: - .span_to_snippet(pat.span.trim_start(begin_par_sp).unwrap()) - .unwrap_or_else(|_| pprust::pat_to_string(&pat)); - - self.struct_span_err(self.prev_token.span, "unexpected closing `)`") - .span_label(begin_par_sp, "opening `(`") - .span_suggestion( - begin_par_sp.to(self.prev_token.span), - "remove parenthesis in `for` loop", - format!("{} in {}", pat_str, pprust::expr_to_string(&expr)), - // With e.g. `for (x) in y)` this would replace `(x) in y)` - // with `x) in y)` which is syntactically invalid. - // However, this is prevented before we get here. - Applicability::MachineApplicable, - ) - .emit(); + self.struct_span_err( + MultiSpan::from_spans(vec![begin_par_sp, self.prev_token.span]), + "unexpected parenthesis surrounding `for` loop head", + ) + .multipart_suggestion( + "remove parenthesis in `for` loop", + vec![(begin_par_sp, String::new()), (self.prev_token.span, String::new())], + // With e.g. `for (x) in y)` this would replace `(x) in y)` + // with `x) in y)` which is syntactically invalid. + // However, this is prevented before we get here. + Applicability::MachineApplicable, + ) + .emit(); // Unwrap `(pat)` into `pat` to avoid the `unused_parens` lint. pat.and_then(|pat| match pat.kind { @@ -1955,7 +1950,19 @@ impl<'a> Parser<'a> { } match self.parse_expr_res(Restrictions::CONST_EXPR, None) { Ok(expr) => { - if token::Comma == self.token.kind || self.token.kind.should_end_const_arg() { + // Find a mistake like `MyTrait<Assoc == S::Assoc>`. + if token::EqEq == snapshot.token.kind { + err.span_suggestion( + snapshot.token.span, + "if you meant to use an associated type binding, replace `==` with `=`", + "=".to_string(), + Applicability::MaybeIncorrect, + ); + let value = self.mk_expr_err(start.to(expr.span)); + err.emit(); + return Ok(GenericArg::Const(AnonConst { id: ast::DUMMY_NODE_ID, value })); + } else if token::Comma == self.token.kind || self.token.kind.should_end_const_arg() + { // Avoid the following output by checking that we consumed a full const arg: // help: expressions must be enclosed in braces to be used as const generic // arguments diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 737f1d9cbb1..d8f9fc9179e 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2042,7 +2042,7 @@ impl<'a> Parser<'a> { self.check_for_for_in_in_typo(self.prev_token.span); let expr = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?; - let pat = self.recover_parens_around_for_head(pat, &expr, begin_paren); + let pat = self.recover_parens_around_for_head(pat, begin_paren); let (iattrs, loop_block) = self.parse_inner_attrs_and_block()?; attrs.extend(iattrs); diff --git a/compiler/rustc_passes/src/hir_id_validator.rs b/compiler/rustc_passes/src/hir_id_validator.rs index 18f61c6e1c1..eff1096c855 100644 --- a/compiler/rustc_passes/src/hir_id_validator.rs +++ b/compiler/rustc_passes/src/hir_id_validator.rs @@ -1,5 +1,5 @@ use rustc_data_structures::fx::FxHashSet; -use rustc_data_structures::sync::{par_iter, Lock, ParallelIterator}; +use rustc_data_structures::sync::Lock; use rustc_hir as hir; use rustc_hir::def_id::{LocalDefId, CRATE_DEF_INDEX}; use rustc_hir::intravisit; @@ -18,9 +18,9 @@ pub fn check_crate(tcx: TyCtxt<'_>) { let errors = Lock::new(Vec::new()); let hir_map = tcx.hir(); - par_iter(&hir_map.krate().modules).for_each(|(&module_id, _)| { + hir_map.par_for_each_module(|module_id| { hir_map - .visit_item_likes_in_module(module_id, &mut OuterVisitor { hir_map, errors: &errors }); + .visit_item_likes_in_module(module_id, &mut OuterVisitor { hir_map, errors: &errors }) }); let errors = errors.into_inner(); diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index b7e43b7785d..d7c354aeb49 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -929,6 +929,16 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) { let declared_lib_features = &tcx.features().declared_lib_features; let mut remaining_lib_features = FxHashMap::default(); for (feature, span) in declared_lib_features { + if !tcx.sess.opts.unstable_features.is_nightly_build() { + struct_span_err!( + tcx.sess, + *span, + E0554, + "`#![feature]` may not be used on the {} release channel", + env!("CFG_RELEASE_CHANNEL") + ) + .emit(); + } if remaining_lib_features.contains_key(&feature) { // Warn if the user enables a lib feature multiple times. duplicate_feature_err(tcx.sess, *span, *feature); diff --git a/compiler/rustc_query_impl/src/keys.rs b/compiler/rustc_query_impl/src/keys.rs index 42e8b4023cf..563a3cf1438 100644 --- a/compiler/rustc_query_impl/src/keys.rs +++ b/compiler/rustc_query_impl/src/keys.rs @@ -449,3 +449,25 @@ impl<'tcx> Key for (ty::Predicate<'tcx>, traits::WellFormedLoc) { DUMMY_SP } } + +impl<'tcx> Key for (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'tcx>>) { + #[inline(always)] + fn query_crate_is_local(&self) -> bool { + true + } + + fn default_span(&self, _: TyCtxt<'_>) -> Span { + DUMMY_SP + } +} + +impl<'tcx> Key for (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>) { + #[inline(always)] + fn query_crate_is_local(&self) -> bool { + true + } + + fn default_span(&self, tcx: TyCtxt<'_>) -> Span { + self.0.default_span(tcx) + } +} diff --git a/compiler/rustc_query_impl/src/on_disk_cache.rs b/compiler/rustc_query_impl/src/on_disk_cache.rs index bfd36bfb2db..d8cff0bd188 100644 --- a/compiler/rustc_query_impl/src/on_disk_cache.rs +++ b/compiler/rustc_query_impl/src/on_disk_cache.rs @@ -1,12 +1,12 @@ use crate::QueryCtxt; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; use rustc_data_structures::memmap::Mmap; -use rustc_data_structures::sync::{HashMapExt, Lock, Lrc, OnceCell, RwLock}; +use rustc_data_structures::sync::{HashMapExt, Lock, Lrc, RwLock}; use rustc_data_structures::unhash::UnhashMap; use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, StableCrateId, LOCAL_CRATE}; use rustc_hir::definitions::DefPathHash; use rustc_index::vec::{Idx, IndexVec}; -use rustc_middle::dep_graph::{DepNode, DepNodeIndex, SerializedDepNodeIndex}; +use rustc_middle::dep_graph::{DepNodeIndex, SerializedDepNodeIndex}; use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState}; use rustc_middle::mir::{self, interpret}; use rustc_middle::thir; @@ -25,7 +25,6 @@ use rustc_span::hygiene::{ use rustc_span::source_map::{SourceMap, StableSourceFileId}; use rustc_span::CachingSourceMapView; use rustc_span::{BytePos, ExpnData, ExpnHash, Pos, SourceFile, Span}; -use std::collections::hash_map::Entry; use std::mem; const TAG_FILE_FOOTER: u128 = 0xC0FFEE_C0FFEE_C0FFEE_C0FFEE_C0FFEE; @@ -51,8 +50,6 @@ pub struct OnDiskCache<'sess> { // session. current_side_effects: Lock<FxHashMap<DepNodeIndex, QuerySideEffects>>, - cnum_map: OnceCell<UnhashMap<StableCrateId, CrateNum>>, - source_map: &'sess SourceMap, file_index_to_stable_id: FxHashMap<SourceFileIndex, EncodedSourceFileId>, @@ -87,27 +84,11 @@ pub struct OnDiskCache<'sess> { expn_data: UnhashMap<ExpnHash, AbsoluteBytePos>, // Additional information used when decoding hygiene data. hygiene_context: HygieneDecodeContext, - // Maps `DefPathHash`es to their `RawDefId`s from the *previous* + // Maps `ExpnHash`es to their raw value from the *previous* // compilation session. This is used as an initial 'guess' when - // we try to map a `DefPathHash` to its `DefId` in the current compilation - // session. - foreign_def_path_hashes: UnhashMap<DefPathHash, RawDefId>, - // Likewise for ExpnId. + // we try to map an `ExpnHash` to its value in the current + // compilation session. foreign_expn_data: UnhashMap<ExpnHash, u32>, - - // The *next* compilation sessison's `foreign_def_path_hashes` - at - // the end of our current compilation session, this will get written - // out to the `foreign_def_path_hashes` field of the `Footer`, which - // will become `foreign_def_path_hashes` of the next compilation session. - // This stores any `DefPathHash` that we may need to map to a `DefId` - // during the next compilation session. - latest_foreign_def_path_hashes: Lock<UnhashMap<DefPathHash, RawDefId>>, - - // Caches all lookups of `DefPathHashes`, both for local and foreign - // definitions. A definition from the previous compilation session - // may no longer exist in the current compilation session, so - // we use `Option<DefId>` so that we can cache a lookup failure. - def_path_hash_to_def_id_cache: Lock<UnhashMap<DefPathHash, Option<DefId>>>, } // This type is used only for serialization and deserialization. @@ -122,7 +103,6 @@ struct Footer { syntax_contexts: FxHashMap<u32, AbsoluteBytePos>, // See `OnDiskCache.expn_data` expn_data: UnhashMap<ExpnHash, AbsoluteBytePos>, - foreign_def_path_hashes: UnhashMap<DefPathHash, RawDefId>, foreign_expn_data: UnhashMap<ExpnHash, u32>, } @@ -145,19 +125,6 @@ impl AbsoluteBytePos { } } -/// Represents a potentially invalid `DefId`. This is used during incremental -/// compilation to represent a `DefId` from the *previous* compilation session, -/// which may no longer be valid. This is used to help map a `DefPathHash` -/// to a `DefId` in the current compilation session. -#[derive(Encodable, Decodable, Copy, Clone, Debug)] -crate struct RawDefId { - // We deliberately do not use `CrateNum` and `DefIndex` - // here, since a crate/index from the previous compilation - // session may no longer exist. - pub krate: u32, - pub index: u32, -} - /// An `EncodedSourceFileId` is the same as a `StableSourceFileId` except that /// the source crate is represented as a [StableCrateId] instead of as a /// `CrateNum`. This way `EncodedSourceFileId` can be encoded and decoded @@ -170,8 +137,8 @@ struct EncodedSourceFileId { } impl EncodedSourceFileId { - fn translate(&self, cnum_map: &UnhashMap<StableCrateId, CrateNum>) -> StableSourceFileId { - let cnum = cnum_map[&self.stable_crate_id]; + fn translate(&self, tcx: TyCtxt<'_>) -> StableSourceFileId { + let cnum = tcx.stable_crate_id_to_crate_num(self.stable_crate_id); StableSourceFileId { file_name_hash: self.file_name_hash, cnum } } @@ -211,7 +178,6 @@ impl<'sess> rustc_middle::ty::OnDiskCache<'sess> for OnDiskCache<'sess> { serialized_data: RwLock::new(Some(data)), file_index_to_stable_id: footer.file_index_to_stable_id, file_index_to_file: Default::default(), - cnum_map: OnceCell::new(), source_map: sess.source_map(), current_side_effects: Default::default(), query_result_index: footer.query_result_index.into_iter().collect(), @@ -221,9 +187,6 @@ impl<'sess> rustc_middle::ty::OnDiskCache<'sess> for OnDiskCache<'sess> { expn_data: footer.expn_data, foreign_expn_data: footer.foreign_expn_data, hygiene_context: Default::default(), - foreign_def_path_hashes: footer.foreign_def_path_hashes, - latest_foreign_def_path_hashes: Default::default(), - def_path_hash_to_def_id_cache: Default::default(), } } @@ -232,7 +195,6 @@ impl<'sess> rustc_middle::ty::OnDiskCache<'sess> for OnDiskCache<'sess> { serialized_data: RwLock::new(None), file_index_to_stable_id: Default::default(), file_index_to_file: Default::default(), - cnum_map: OnceCell::new(), source_map, current_side_effects: Default::default(), query_result_index: Default::default(), @@ -242,9 +204,6 @@ impl<'sess> rustc_middle::ty::OnDiskCache<'sess> for OnDiskCache<'sess> { expn_data: UnhashMap::default(), foreign_expn_data: UnhashMap::default(), hygiene_context: Default::default(), - foreign_def_path_hashes: Default::default(), - latest_foreign_def_path_hashes: Default::default(), - def_path_hash_to_def_id_cache: Default::default(), } } @@ -254,13 +213,6 @@ impl<'sess> rustc_middle::ty::OnDiskCache<'sess> for OnDiskCache<'sess> { /// In order to serialize the new on-disk cache, the former on-disk cache file needs to be /// deleted, hence we won't be able to refer to its memmapped data. fn drop_serialized_data(&self, tcx: TyCtxt<'tcx>) { - // Register any dep nodes that we reused from the previous session, - // but didn't `DepNode::construct` in this session. This ensures - // that their `DefPathHash` to `RawDefId` mappings are registered - // in 'latest_foreign_def_path_hashes' if necessary, since that - // normally happens in `DepNode::construct`. - tcx.dep_graph.register_reused_dep_nodes(tcx); - // Load everything into memory so we can write it out to the on-disk // cache. The vast majority of cacheable query results should already // be in memory, so this should be a cheap operation. @@ -294,7 +246,6 @@ impl<'sess> rustc_middle::ty::OnDiskCache<'sess> for OnDiskCache<'sess> { (file_to_file_index, file_index_to_stable_id) }; - let latest_foreign_def_path_hashes = self.latest_foreign_def_path_hashes.lock().clone(); let hygiene_encode_context = HygieneEncodeContext::default(); let mut encoder = CacheEncoder { @@ -306,7 +257,6 @@ impl<'sess> rustc_middle::ty::OnDiskCache<'sess> for OnDiskCache<'sess> { source_map: CachingSourceMapView::new(tcx.sess.source_map()), file_to_file_index, hygiene_context: &hygiene_encode_context, - latest_foreign_def_path_hashes, }; // Encode query results. @@ -383,9 +333,6 @@ impl<'sess> rustc_middle::ty::OnDiskCache<'sess> for OnDiskCache<'sess> { }, )?; - let foreign_def_path_hashes = - std::mem::take(&mut encoder.latest_foreign_def_path_hashes); - // `Encode the file footer. let footer_pos = encoder.position() as u64; encoder.encode_tagged( @@ -398,7 +345,6 @@ impl<'sess> rustc_middle::ty::OnDiskCache<'sess> for OnDiskCache<'sess> { syntax_contexts, expn_data, foreign_expn_data, - foreign_def_path_hashes, }, )?; @@ -413,80 +359,21 @@ impl<'sess> rustc_middle::ty::OnDiskCache<'sess> for OnDiskCache<'sess> { }) } - fn def_path_hash_to_def_id(&self, tcx: TyCtxt<'tcx>, hash: DefPathHash) -> Option<DefId> { - let mut cache = self.def_path_hash_to_def_id_cache.lock(); - match cache.entry(hash) { - Entry::Occupied(e) => *e.get(), - Entry::Vacant(e) => { - debug!("def_path_hash_to_def_id({:?})", hash); - // Check if the `DefPathHash` corresponds to a definition in the current - // crate - if let Some(def_id) = - tcx.definitions_untracked().local_def_path_hash_to_def_id(hash) - { - let def_id = def_id.to_def_id(); - e.insert(Some(def_id)); - return Some(def_id); - } - // This `raw_def_id` represents the `DefId` of this `DefPathHash` in - // the *previous* compliation session. The `DefPathHash` includes the - // owning crate, so if the corresponding definition still exists in the - // current compilation session, the crate is guaranteed to be the same - // (otherwise, we would compute a different `DefPathHash`). - let raw_def_id = self.get_raw_def_id(&hash)?; - debug!("def_path_hash_to_def_id({:?}): raw_def_id = {:?}", hash, raw_def_id); - // If the owning crate no longer exists, the corresponding definition definitely - // no longer exists. - let krate = self.try_remap_cnum(tcx, hash.stable_crate_id())?; - debug!("def_path_hash_to_def_id({:?}): krate = {:?}", hash, krate); - // If our `DefPathHash` corresponded to a definition in the local crate, - // we should have either found it in `local_def_path_hash_to_def_id`, or - // never attempted to load it in the first place. Any query result or `DepNode` - // that references a local `DefId` should depend on some HIR-related `DepNode`. - // If a local definition is removed/modified such that its old `DefPathHash` - // no longer has a corresponding definition, that HIR-related `DepNode` should - // end up red. This should prevent us from ever calling - // `tcx.def_path_hash_to_def_id`, since we'll end up recomputing any - // queries involved. - debug_assert_ne!(krate, LOCAL_CRATE); - // Try to find a definition in the current session, using the previous `DefIndex` - // as an initial guess. - let opt_def_id = - tcx.cstore_untracked().def_path_hash_to_def_id(krate, raw_def_id.index, hash); - debug!("def_path_to_def_id({:?}): opt_def_id = {:?}", hash, opt_def_id); - e.insert(opt_def_id); - opt_def_id - } - } - } + fn def_path_hash_to_def_id(&self, tcx: TyCtxt<'tcx>, hash: DefPathHash) -> DefId { + debug!("def_path_hash_to_def_id({:?})", hash); - fn register_reused_dep_node(&self, tcx: TyCtxt<'sess>, dep_node: &DepNode) { - // For reused dep nodes, we only need to store the mapping if the node - // is one whose query key we can reconstruct from the hash. We use the - // mapping to aid that reconstruction in the next session. While we also - // use it to decode `DefId`s we encoded in the cache as `DefPathHashes`, - // they're already registered during `DefId` encoding. - if dep_node.kind.can_reconstruct_query_key() { - let hash = DefPathHash(dep_node.hash.into()); - - // We can't simply copy the `RawDefId` from `foreign_def_path_hashes` to - // `latest_foreign_def_path_hashes`, since the `RawDefId` might have - // changed in the current compilation session (e.g. we've added/removed crates, - // or added/removed definitions before/after the target definition). - if let Some(def_id) = self.def_path_hash_to_def_id(tcx, hash) { - if !def_id.is_local() { - self.store_foreign_def_id_hash(def_id, hash); - } - } - } - } + let stable_crate_id = hash.stable_crate_id(); - fn store_foreign_def_id_hash(&self, def_id: DefId, hash: DefPathHash) { - // We may overwrite an existing entry, but it will have the same value, - // so it's fine - self.latest_foreign_def_path_hashes - .lock() - .insert(hash, RawDefId { krate: def_id.krate.as_u32(), index: def_id.index.as_u32() }); + // If this is a DefPathHash from the local crate, we can look up the + // DefId in the tcx's `Definitions`. + if stable_crate_id == tcx.sess.local_stable_crate_id() { + tcx.definitions_untracked().local_def_path_hash_to_def_id(hash).to_def_id() + } else { + // If this is a DefPathHash from an upstream crate, let the CrateStore map + // it to a DefId. + let cnum = tcx.cstore_untracked().stable_crate_id_to_crate_num(stable_crate_id); + tcx.cstore_untracked().def_path_hash_to_def_id(cnum, hash) + } } } @@ -518,17 +405,6 @@ impl<'sess> OnDiskCache<'sess> { debug_assert!(prev.is_none()); } - fn get_raw_def_id(&self, hash: &DefPathHash) -> Option<RawDefId> { - self.foreign_def_path_hashes.get(hash).copied() - } - - fn try_remap_cnum(&self, tcx: TyCtxt<'_>, stable_crate_id: StableCrateId) -> Option<CrateNum> { - let cnum_map = self.cnum_map.get_or_init(|| Self::compute_cnum_map(tcx)); - debug!("try_remap_cnum({:?}): cnum_map={:?}", stable_crate_id, cnum_map); - - cnum_map.get(&stable_crate_id).copied() - } - /// Returns the cached query result if there is something in the cache for /// the given `SerializedDepNodeIndex`; otherwise returns `None`. pub fn try_load_query_result<'tcx, T>( @@ -586,14 +462,11 @@ impl<'sess> OnDiskCache<'sess> { where T: Decodable<CacheDecoder<'a, 'tcx>>, { - let cnum_map = self.cnum_map.get_or_init(|| Self::compute_cnum_map(tcx)); - let serialized_data = self.serialized_data.read(); let mut decoder = CacheDecoder { tcx, opaque: opaque::Decoder::new(serialized_data.as_deref().unwrap_or(&[]), pos.to_usize()), source_map: self.source_map, - cnum_map, file_index_to_file: &self.file_index_to_file, file_index_to_stable_id: &self.file_index_to_stable_id, alloc_decoding_session: self.alloc_decoding_state.new_decoding_session(), @@ -604,23 +477,6 @@ impl<'sess> OnDiskCache<'sess> { }; f(&mut decoder) } - - // This function builds mapping from previous-session-`CrateNum` to - // current-session-`CrateNum`. There might be `CrateNum`s from the previous - // `Session` that don't occur in the current one. For these, the mapping - // maps to None. - fn compute_cnum_map(tcx: TyCtxt<'_>) -> UnhashMap<StableCrateId, CrateNum> { - tcx.dep_graph.with_ignore(|| { - tcx.crates(()) - .iter() - .chain(std::iter::once(&LOCAL_CRATE)) - .map(|&cnum| { - let hash = tcx.def_path_hash(cnum.as_def_id()).stable_crate_id(); - (hash, cnum) - }) - .collect() - }) - } } //- DECODING ------------------------------------------------------------------- @@ -632,7 +488,6 @@ pub struct CacheDecoder<'a, 'tcx> { tcx: TyCtxt<'tcx>, opaque: opaque::Decoder<'a>, source_map: &'a SourceMap, - cnum_map: &'a UnhashMap<StableCrateId, CrateNum>, file_index_to_file: &'a Lock<FxHashMap<SourceFileIndex, Lrc<SourceFile>>>, file_index_to_stable_id: &'a FxHashMap<SourceFileIndex, EncodedSourceFileId>, alloc_decoding_session: AllocDecodingSession<'a>, @@ -645,10 +500,10 @@ pub struct CacheDecoder<'a, 'tcx> { impl<'a, 'tcx> CacheDecoder<'a, 'tcx> { fn file_index_to_file(&self, index: SourceFileIndex) -> Lrc<SourceFile> { let CacheDecoder { + tcx, ref file_index_to_file, ref file_index_to_stable_id, ref source_map, - ref cnum_map, .. } = *self; @@ -656,7 +511,7 @@ impl<'a, 'tcx> CacheDecoder<'a, 'tcx> { .borrow_mut() .entry(index) .or_insert_with(|| { - let stable_id = file_index_to_stable_id[&index].translate(cnum_map); + let stable_id = file_index_to_stable_id[&index].translate(tcx); source_map .source_file_by_stable_id(stable_id) .expect("failed to lookup `SourceFile` in new context") @@ -798,7 +653,7 @@ impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for ExpnId { return Ok(expn_id); } - let krate = decoder.cnum_map[&hash.stable_crate_id()]; + let krate = decoder.tcx.stable_crate_id_to_crate_num(hash.stable_crate_id()); let expn_id = if krate == LOCAL_CRATE { // We look up the position of the associated `ExpnData` and decode it. @@ -871,7 +726,7 @@ impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for Span { impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for CrateNum { fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> { let stable_id = StableCrateId::decode(d)?; - let cnum = d.cnum_map[&stable_id]; + let cnum = d.tcx.stable_crate_id_to_crate_num(stable_id); Ok(cnum) } } @@ -899,12 +754,7 @@ impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for DefId { // If we get to this point, then all of the query inputs were green, // which means that the definition with this hash is guaranteed to // still exist in the current compilation session. - Ok(d.tcx() - .on_disk_cache - .as_ref() - .unwrap() - .def_path_hash_to_def_id(d.tcx(), def_path_hash) - .unwrap()) + Ok(d.tcx().on_disk_cache.as_ref().unwrap().def_path_hash_to_def_id(d.tcx(), def_path_hash)) } } @@ -969,7 +819,6 @@ pub struct CacheEncoder<'a, 'tcx, E: OpaqueEncoder> { source_map: CachingSourceMapView<'tcx>, file_to_file_index: FxHashMap<*const SourceFile, SourceFileIndex>, hygiene_context: &'a HygieneEncodeContext, - latest_foreign_def_path_hashes: UnhashMap<DefPathHash, RawDefId>, } impl<'a, 'tcx, E> CacheEncoder<'a, 'tcx, E> @@ -1102,17 +951,7 @@ where E: 'a + OpaqueEncoder, { fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> { - let def_path_hash = s.tcx.def_path_hash(*self); - // Store additional information when we encode a foreign `DefId`, - // so that we can map its `DefPathHash` back to a `DefId` in the next - // compilation session. - if !self.is_local() { - s.latest_foreign_def_path_hashes.insert( - def_path_hash, - RawDefId { krate: self.krate.as_u32(), index: self.index.as_u32() }, - ); - } - def_path_hash.encode(s) + s.tcx.def_path_hash(*self).encode(s) } } diff --git a/compiler/rustc_query_system/src/dep_graph/dep_node.rs b/compiler/rustc_query_system/src/dep_graph/dep_node.rs index 59ef6052a60..46dc0c720ce 100644 --- a/compiler/rustc_query_system/src/dep_graph/dep_node.rs +++ b/compiler/rustc_query_system/src/dep_graph/dep_node.rs @@ -53,18 +53,6 @@ use std::hash::Hash; #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)] pub struct DepNode<K> { pub kind: K, - // Important - whenever a `DepNode` is constructed, we need to make - // sure to register a `DefPathHash -> DefId` mapping if needed. - // This is currently done in two places: - // - // * When a `DepNode::construct` is called, `arg.to_fingerprint()` - // is responsible for calling `OnDiskCache::store_foreign_def_id_hash` - // if needed - // * When we serialize the on-disk cache, `OnDiskCache::serialize` is - // responsible for calling `DepGraph::register_reused_dep_nodes`. - // - // FIXME: Enforce this by preventing manual construction of `DefNode` - // (e.g. add a `_priv: ()` field) pub hash: PackedFingerprint, } diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index e589d16992f..23a43771842 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -760,20 +760,6 @@ impl<K: DepKind> DepGraph<K> { } } - // Register reused dep nodes (i.e. nodes we've marked red or green) with the context. - pub fn register_reused_dep_nodes<Ctxt: DepContext<DepKind = K>>(&self, tcx: Ctxt) { - let data = self.data.as_ref().unwrap(); - for prev_index in data.colors.values.indices() { - match data.colors.get(prev_index) { - Some(DepNodeColor::Red) | Some(DepNodeColor::Green(_)) => { - let dep_node = data.previous.index_to_node(prev_index); - tcx.register_reused_dep_node(&dep_node); - } - None => {} - } - } - } - pub fn print_incremental_info(&self) { if let Some(data) = &self.data { data.current.encoder.borrow().print_incremental_info( diff --git a/compiler/rustc_query_system/src/dep_graph/mod.rs b/compiler/rustc_query_system/src/dep_graph/mod.rs index 15e2633c4f1..b5be1192ce7 100644 --- a/compiler/rustc_query_system/src/dep_graph/mod.rs +++ b/compiler/rustc_query_system/src/dep_graph/mod.rs @@ -27,8 +27,6 @@ pub trait DepContext: Copy { /// Access the DepGraph. fn dep_graph(&self) -> &DepGraph<Self::DepKind>; - fn register_reused_dep_node(&self, dep_node: &DepNode<Self::DepKind>); - /// Access the profiler. fn profiler(&self) -> &SelfProfilerRef; diff --git a/compiler/rustc_query_system/src/dep_graph/serialized.rs b/compiler/rustc_query_system/src/dep_graph/serialized.rs index 73c00fc49ba..f5f67fcd0a0 100644 --- a/compiler/rustc_query_system/src/dep_graph/serialized.rs +++ b/compiler/rustc_query_system/src/dep_graph/serialized.rs @@ -99,7 +99,7 @@ impl<K: DepKind> SerializedDepGraph<K> { impl<'a, K: DepKind + Decodable<opaque::Decoder<'a>>> Decodable<opaque::Decoder<'a>> for SerializedDepGraph<K> { - #[instrument(skip(d))] + #[instrument(level = "debug", skip(d))] fn decode(d: &mut opaque::Decoder<'a>) -> Result<SerializedDepGraph<K>, String> { let start_position = d.position(); @@ -187,7 +187,7 @@ impl<K: DepKind> EncoderState<K> { } } - #[instrument(skip(self, record_graph))] + #[instrument(level = "debug", skip(self, record_graph))] fn encode_node( &mut self, node: &NodeInfo<K>, diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index 4c1d537d55f..a158e0e48e8 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -1652,7 +1652,11 @@ fn extract_labels(ctxt: &mut LifetimeContext<'_, '_>, body: &hir::Body<'_>) { } fn expression_label(ex: &hir::Expr<'_>) -> Option<Ident> { - if let hir::ExprKind::Loop(_, Some(label), ..) = ex.kind { Some(label.ident) } else { None } + match ex.kind { + hir::ExprKind::Loop(_, Some(label), ..) => Some(label.ident), + hir::ExprKind::Block(_, Some(label)) => Some(label.ident), + _ => None, + } } fn check_if_label_shadows_lifetime(tcx: TyCtxt<'_>, mut scope: ScopeRef<'_>, label: Ident) { @@ -2024,7 +2028,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { // ensure that we issue lints in a repeatable order def_ids.sort_by_cached_key(|&def_id| self.tcx.def_path_hash(def_id)); - for def_id in def_ids { + 'lifetimes: for def_id in def_ids { debug!("check_uses_for_lifetimes_defined_by_scope: def_id = {:?}", def_id); let lifetimeuseset = self.lifetime_uses.remove(&def_id); @@ -2067,6 +2071,27 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { { continue; } + + // opaque types generated when desugaring an async function can have a single + // use lifetime even if it is explicitly denied (Issue #77175) + if let hir::Node::Item(hir::Item { + kind: hir::ItemKind::OpaqueTy(ref opaque), + .. + }) = self.tcx.hir().get(parent_hir_id) + { + if opaque.origin != hir::OpaqueTyOrigin::AsyncFn { + continue 'lifetimes; + } + // We want to do this only if the liftime identifier is already defined + // in the async function that generated this. Otherwise it could be + // an opaque type defined by the developer and we still want this + // lint to fail compilation + for p in opaque.generics.params { + if defined_by.contains_key(&p.name) { + continue 'lifetimes; + } + } + } } } diff --git a/compiler/rustc_span/src/caching_source_map_view.rs b/compiler/rustc_span/src/caching_source_map_view.rs index 8e21b9ff44a..fdabf404a37 100644 --- a/compiler/rustc_span/src/caching_source_map_view.rs +++ b/compiler/rustc_span/src/caching_source_map_view.rs @@ -215,13 +215,13 @@ impl<'sm> CachingSourceMapView<'sm> { // Span lo and hi may equal line end when last line doesn't // end in newline, hence the inclusive upper bounds below. - debug_assert!(span_data.lo >= lo.line.start); - debug_assert!(span_data.lo <= lo.line.end); - debug_assert!(span_data.hi >= hi.line.start); - debug_assert!(span_data.hi <= hi.line.end); - debug_assert!(lo.file.contains(span_data.lo)); - debug_assert!(lo.file.contains(span_data.hi)); - debug_assert_eq!(lo.file_index, hi.file_index); + assert!(span_data.lo >= lo.line.start); + assert!(span_data.lo <= lo.line.end); + assert!(span_data.hi >= hi.line.start); + assert!(span_data.hi <= hi.line.end); + assert!(lo.file.contains(span_data.lo)); + assert!(lo.file.contains(span_data.hi)); + assert_eq!(lo.file_index, hi.file_index); Some(( lo.file.clone(), diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index eb496140553..9c5469f635f 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -78,7 +78,7 @@ mod tests; // threads within the compilation session, but is not accessible outside the // session. pub struct SessionGlobals { - symbol_interner: Lock<symbol::Interner>, + symbol_interner: symbol::Interner, span_interner: Lock<span_encoding::SpanInterner>, hygiene_data: Lock<hygiene::HygieneData>, source_map: Lock<Option<Lrc<SourceMap>>>, @@ -87,7 +87,7 @@ pub struct SessionGlobals { impl SessionGlobals { pub fn new(edition: Edition) -> SessionGlobals { SessionGlobals { - symbol_interner: Lock::new(symbol::Interner::fresh()), + symbol_interner: symbol::Interner::fresh(), span_interner: Lock::new(span_encoding::SpanInterner::default()), hygiene_data: Lock::new(hygiene::HygieneData::new(edition)), source_map: Lock::new(None), diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 760357644a5..322bea3806c 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -5,6 +5,7 @@ use rustc_arena::DroplessArena; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey}; +use rustc_data_structures::sync::Lock; use rustc_macros::HashStable_Generic; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; @@ -923,6 +924,7 @@ symbols! { panic_2021, panic_abort, panic_bounds_check, + panic_display, panic_fmt, panic_handler, panic_impl, @@ -1210,6 +1212,7 @@ symbols! { simd_select_bitmask, simd_shl, simd_shr, + simd_shuffle, simd_sub, simd_trunc, simd_xor, @@ -1622,14 +1625,15 @@ impl Symbol { /// Maps a string to its interned representation. pub fn intern(string: &str) -> Self { - with_interner(|interner| interner.intern(string)) + with_session_globals(|session_globals| session_globals.symbol_interner.intern(string)) } /// Convert to a `SymbolStr`. This is a slowish operation because it /// requires locking the symbol interner. pub fn as_str(self) -> SymbolStr { - with_interner(|interner| unsafe { - SymbolStr { string: std::mem::transmute::<&str, &str>(interner.get(self)) } + with_session_globals(|session_globals| { + let symbol_str = session_globals.symbol_interner.get(self); + unsafe { SymbolStr { string: std::mem::transmute::<&str, &str>(symbol_str) } } }) } @@ -1638,7 +1642,7 @@ impl Symbol { } pub fn len(self) -> usize { - with_interner(|interner| interner.get(self).len()) + with_session_globals(|session_globals| session_globals.symbol_interner.get(self).len()) } pub fn is_empty(self) -> bool { @@ -1695,6 +1699,9 @@ impl<CTX> ToStableHashKey<CTX> for Symbol { } } +#[derive(Default)] +pub(crate) struct Interner(Lock<InternerInner>); + // The `&'static str`s in this type actually point into the arena. // // The `FxHashMap`+`Vec` pair could be replaced by `FxIndexSet`, but #75278 @@ -1704,7 +1711,7 @@ impl<CTX> ToStableHashKey<CTX> for Symbol { // This type is private to prevent accidentally constructing more than one `Interner` on the same // thread, which makes it easy to mixup `Symbol`s between `Interner`s. #[derive(Default)] -pub(crate) struct Interner { +struct InternerInner { arena: DroplessArena, names: FxHashMap<&'static str, Symbol>, strings: Vec<&'static str>, @@ -1712,37 +1719,38 @@ pub(crate) struct Interner { impl Interner { fn prefill(init: &[&'static str]) -> Self { - Interner { + Interner(Lock::new(InternerInner { strings: init.into(), names: init.iter().copied().zip((0..).map(Symbol::new)).collect(), ..Default::default() - } + })) } #[inline] - pub fn intern(&mut self, string: &str) -> Symbol { - if let Some(&name) = self.names.get(string) { + fn intern(&self, string: &str) -> Symbol { + let mut inner = self.0.lock(); + if let Some(&name) = inner.names.get(string) { return name; } - let name = Symbol::new(self.strings.len() as u32); + let name = Symbol::new(inner.strings.len() as u32); // `from_utf8_unchecked` is safe since we just allocated a `&str` which is known to be // UTF-8. let string: &str = - unsafe { str::from_utf8_unchecked(self.arena.alloc_slice(string.as_bytes())) }; + unsafe { str::from_utf8_unchecked(inner.arena.alloc_slice(string.as_bytes())) }; // It is safe to extend the arena allocation to `'static` because we only access // these while the arena is still alive. let string: &'static str = unsafe { &*(string as *const str) }; - self.strings.push(string); - self.names.insert(string, name); + inner.strings.push(string); + inner.names.insert(string, name); name } // Get the symbol as a string. `Symbol::as_str()` should be used in // preference to this function. - pub fn get(&self, symbol: Symbol) -> &str { - self.strings[symbol.0.as_usize()] + fn get(&self, symbol: Symbol) -> &str { + self.0.lock().strings[symbol.0.as_usize()] } } @@ -1873,11 +1881,6 @@ impl Ident { } } -#[inline] -fn with_interner<T, F: FnOnce(&mut Interner) -> T>(f: F) -> T { - with_session_globals(|session_globals| f(&mut *session_globals.symbol_interner.lock())) -} - /// An alternative to [`Symbol`], useful when the chars within the symbol need to /// be accessed. It deliberately has limited functionality and should only be /// used for temporary values. diff --git a/compiler/rustc_span/src/symbol/tests.rs b/compiler/rustc_span/src/symbol/tests.rs index 11dea265b4e..0958fce5fee 100644 --- a/compiler/rustc_span/src/symbol/tests.rs +++ b/compiler/rustc_span/src/symbol/tests.rs @@ -4,7 +4,7 @@ use crate::create_default_session_globals_then; #[test] fn interner_tests() { - let mut i: Interner = Interner::default(); + let i = Interner::default(); // first one is zero: assert_eq!(i.intern("dog"), Symbol::new(0)); // re-use gets the same entry: diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs index 4f52535aa50..d9eb299e2fd 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/abi/call/mod.rs @@ -1,6 +1,7 @@ use crate::abi::{self, Abi, Align, FieldsShape, Size}; use crate::abi::{HasDataLayout, TyAbiInterface, TyAndLayout}; use crate::spec::{self, HasTargetSpec}; +use std::fmt; mod aarch64; mod amdgpu; @@ -25,7 +26,7 @@ mod x86; mod x86_64; mod x86_win64; -#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable_Generic)] pub enum PassMode { /// Ignore the argument. /// @@ -60,7 +61,7 @@ pub use attr_impl::ArgAttribute; mod attr_impl { // The subset of llvm::Attribute needed for arguments, packed into a bitfield. bitflags::bitflags! { - #[derive(Default)] + #[derive(Default, HashStable_Generic)] pub struct ArgAttribute: u16 { const NoAlias = 1 << 1; const NoCapture = 1 << 2; @@ -77,7 +78,7 @@ mod attr_impl { /// Sometimes an ABI requires small integers to be extended to a full or partial register. This enum /// defines if this extension should be zero-extension or sign-extension when necessary. When it is /// not necessary to extend the argument, this enum is ignored. -#[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)] pub enum ArgExtension { None, Zext, @@ -86,7 +87,7 @@ pub enum ArgExtension { /// A compact representation of LLVM attributes (at least those relevant for this module) /// that can be manipulated without interacting with LLVM's Attribute machinery. -#[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)] pub struct ArgAttributes { pub regular: ArgAttribute, pub arg_ext: ArgExtension, @@ -127,14 +128,14 @@ impl ArgAttributes { } } -#[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)] pub enum RegKind { Integer, Float, Vector, } -#[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)] pub struct Reg { pub kind: RegKind, pub size: Size, @@ -184,7 +185,7 @@ impl Reg { /// An argument passed entirely registers with the /// same kind (e.g., HFA / HVA on PPC64 and AArch64). -#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable_Generic)] pub struct Uniform { pub unit: Reg, @@ -209,7 +210,7 @@ impl Uniform { } } -#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable_Generic)] pub struct CastTarget { pub prefix: [Option<RegKind>; 8], pub prefix_chunk_size: Size, @@ -437,7 +438,7 @@ impl<'a, Ty> TyAndLayout<'a, Ty> { /// Information about how to pass an argument to, /// or return a value from, a function, under some ABI. -#[derive(Debug)] +#[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)] pub struct ArgAbi<'a, Ty> { pub layout: TyAndLayout<'a, Ty>, @@ -545,7 +546,7 @@ impl<'a, Ty> ArgAbi<'a, Ty> { } } -#[derive(Copy, Clone, PartialEq, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)] pub enum Conv { // General language calling conventions, for which every target // should have its own backend (e.g. LLVM) support. @@ -579,7 +580,7 @@ pub enum Conv { /// /// I will do my best to describe this structure, but these /// comments are reverse-engineered and may be inaccurate. -NDM -#[derive(Debug)] +#[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)] pub struct FnAbi<'a, Ty> { /// The LLVM types of each argument. pub args: Vec<ArgAbi<'a, Ty>>, @@ -600,8 +601,29 @@ pub struct FnAbi<'a, Ty> { pub can_unwind: bool, } +/// Error produced by attempting to adjust a `FnAbi`, for a "foreign" ABI. +#[derive(Clone, Debug, HashStable_Generic)] +pub enum AdjustForForeignAbiError { + /// Target architecture doesn't support "foreign" (i.e. non-Rust) ABIs. + Unsupported { arch: String, abi: spec::abi::Abi }, +} + +impl fmt::Display for AdjustForForeignAbiError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Unsupported { arch, abi } => { + write!(f, "target architecture {:?} does not support `extern {}` ABI", arch, abi) + } + } + } +} + impl<'a, Ty> FnAbi<'a, Ty> { - pub fn adjust_for_cabi<C>(&mut self, cx: &C, abi: spec::abi::Abi) -> Result<(), String> + pub fn adjust_for_foreign_abi<C>( + &mut self, + cx: &C, + abi: spec::abi::Abi, + ) -> Result<(), AdjustForForeignAbiError> where Ty: TyAbiInterface<'a, C> + Copy, C: HasDataLayout + HasTargetSpec, @@ -657,7 +679,9 @@ impl<'a, Ty> FnAbi<'a, Ty> { } "asmjs" => wasm::compute_c_abi_info(cx, self), "bpf" => bpf::compute_abi_info(self), - a => return Err(format!("unrecognized arch \"{}\" in target specification", a)), + arch => { + return Err(AdjustForForeignAbiError::Unsupported { arch: arch.to_string(), abi }); + } } Ok(()) diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs index b743c809ca2..8abcdb5e89b 100644 --- a/compiler/rustc_trait_selection/src/opaque_types.rs +++ b/compiler/rustc_trait_selection/src/opaque_types.rs @@ -499,7 +499,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { /// - `substs`, the substs used to instantiate this opaque type /// - `instantiated_ty`, the inferred type C1 -- fully resolved, lifted version of /// `opaque_defn.concrete_ty` - #[instrument(skip(self))] + #[instrument(level = "debug", skip(self))] fn infer_opaque_definition_from_instantiation( &self, opaque_type_key: OpaqueTypeKey<'tcx>, @@ -863,7 +863,7 @@ struct Instantiator<'a, 'tcx> { } impl<'a, 'tcx> Instantiator<'a, 'tcx> { - #[instrument(skip(self))] + #[instrument(level = "debug", skip(self))] fn instantiate_opaque_types_in_map<T: TypeFoldable<'tcx>>(&mut self, value: T) -> T { let tcx = self.infcx.tcx; value.fold_with(&mut BottomUpFolder { diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index d5660c1c7ba..b966779500b 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -974,6 +974,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { param_env: ty::ParamEnv<'tcx>, trait_ref: ty::ConstnessAnd<ty::PolyTraitRef<'tcx>>, ) -> Option<EvaluationResult> { + // Neither the global nor local cache is aware of intercrate + // mode, so don't do any caching. In particular, we might + // re-use the same `InferCtxt` with both an intercrate + // and non-intercrate `SelectionContext` + if self.intercrate { + return None; + } + let tcx = self.tcx(); if self.can_use_global_caches(param_env) { if let Some(res) = tcx.evaluation_cache.get(¶m_env.and(trait_ref), tcx) { @@ -996,6 +1004,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { return; } + // Neither the global nor local cache is aware of intercrate + // mode, so don't do any caching. In particular, we might + // re-use the same `InferCtxt` with both an intercrate + // and non-intercrate `SelectionContext` + if self.intercrate { + return; + } + if self.can_use_global_caches(param_env) { if !trait_ref.needs_infer() { debug!(?trait_ref, ?result, "insert_evaluation_cache global"); @@ -1052,6 +1068,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// /// The weird return type of this function allows it to be used with the `try` (`?`) /// operator within certain functions. + #[inline(always)] fn check_recursion_limit<T: Display + TypeFoldable<'tcx>, V: Display + TypeFoldable<'tcx>>( &self, obligation: &Obligation<'tcx, T>, @@ -2017,7 +2034,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let cause = ObligationCause::new( obligation.cause.span, obligation.cause.body_id, - ObligationCauseCode::MatchImpl(Lrc::new(obligation.cause.code.clone()), impl_def_id), + ObligationCauseCode::MatchImpl(obligation.cause.clone(), impl_def_id), ); let InferOk { obligations, .. } = self diff --git a/compiler/rustc_typeck/src/check/cast.rs b/compiler/rustc_typeck/src/check/cast.rs index 14550690e63..4ea7a8694c0 100644 --- a/compiler/rustc_typeck/src/check/cast.rs +++ b/compiler/rustc_typeck/src/check/cast.rs @@ -362,6 +362,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { ), self.cast_ty, AllowTwoPhase::No, + None, ) .is_ok() { @@ -379,6 +380,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { ), self.cast_ty, AllowTwoPhase::No, + None, ) .is_ok() { @@ -394,6 +396,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { fcx.tcx.mk_ref(reg, TypeAndMut { ty: self.expr_ty, mutbl }), self.cast_ty, AllowTwoPhase::No, + None, ) .is_ok() { @@ -409,6 +412,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { ), self.cast_ty, AllowTwoPhase::No, + None, ) .is_ok() { @@ -666,6 +670,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { self.expr_ty, fcx.tcx.mk_fn_ptr(f), AllowTwoPhase::No, + None, ); if let Err(TypeError::IntrinsicCast) = res { return Err(CastError::IllegalCast); @@ -829,7 +834,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { // Coerce to a raw pointer so that we generate AddressOf in MIR. let array_ptr_type = fcx.tcx.mk_ptr(m_expr); - fcx.try_coerce(self.expr, self.expr_ty, array_ptr_type, AllowTwoPhase::No) + fcx.try_coerce(self.expr, self.expr_ty, array_ptr_type, AllowTwoPhase::No, None) .unwrap_or_else(|_| { bug!( "could not cast from reference to array to pointer to array ({:?} to {:?})", @@ -861,7 +866,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { } fn try_coercion_cast(&self, fcx: &FnCtxt<'a, 'tcx>) -> Result<(), ty::error::TypeError<'_>> { - match fcx.try_coerce(self.expr, self.expr_ty, self.cast_ty, AllowTwoPhase::No) { + match fcx.try_coerce(self.expr, self.expr_ty, self.cast_ty, AllowTwoPhase::No, None) { Ok(_) => Ok(()), Err(err) => Err(err), } diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 1fd1253e527..54e4eb47688 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -214,7 +214,7 @@ pub(super) fn check_fn<'a, 'tcx>( fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType); } else { fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType); - fcx.check_return_expr(&body.value); + fcx.check_return_expr(&body.value, false); } fcx.in_tail_expr = false; diff --git a/compiler/rustc_typeck/src/check/coercion.rs b/compiler/rustc_typeck/src/check/coercion.rs index 013aecae586..92d0470bc2f 100644 --- a/compiler/rustc_typeck/src/check/coercion.rs +++ b/compiler/rustc_typeck/src/check/coercion.rs @@ -935,11 +935,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr_ty: Ty<'tcx>, target: Ty<'tcx>, allow_two_phase: AllowTwoPhase, + cause: Option<ObligationCause<'tcx>>, ) -> RelateResult<'tcx, Ty<'tcx>> { let source = self.resolve_vars_with_obligations(expr_ty); debug!("coercion::try({:?}: {:?} -> {:?})", expr, source, target); - let cause = self.cause(expr.span, ObligationCauseCode::ExprAssignable); + let cause = + cause.unwrap_or_else(|| self.cause(expr.span, ObligationCauseCode::ExprAssignable)); let coerce = Coerce::new(self, cause, allow_two_phase); let ok = self.commit_if_ok(|_| coerce.coerce(source, target))?; @@ -1363,7 +1365,13 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { // Special-case the first expression we are coercing. // To be honest, I'm not entirely sure why we do this. // We don't allow two-phase borrows, see comment in try_find_coercion_lub for why - fcx.try_coerce(expression, expression_ty, self.expected_ty, AllowTwoPhase::No) + fcx.try_coerce( + expression, + expression_ty, + self.expected_ty, + AllowTwoPhase::No, + Some(cause.clone()), + ) } else { match self.expressions { Expressions::Dynamic(ref exprs) => fcx.try_find_coercion_lub( diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs index a86db2d31b3..722b110ed61 100644 --- a/compiler/rustc_typeck/src/check/demand.rs +++ b/compiler/rustc_typeck/src/check/demand.rs @@ -134,7 +134,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> (Ty<'tcx>, Option<DiagnosticBuilder<'tcx>>) { let expected = self.resolve_vars_with_obligations(expected); - let e = match self.try_coerce(expr, checked_ty, expected, allow_two_phase) { + let e = match self.try_coerce(expr, checked_ty, expected, allow_two_phase, None) { Ok(ty) => return (ty, None), Err(e) => e, }; diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index 917adf0e2b9..11b6c93a115 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -765,7 +765,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if self.ret_coercion_span.get().is_none() { self.ret_coercion_span.set(Some(e.span)); } - self.check_return_expr(e); + self.check_return_expr(e, true); } else { let mut coercion = self.ret_coercion.as_ref().unwrap().borrow_mut(); if self.ret_coercion_span.get().is_none() { @@ -794,16 +794,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx.types.never } - pub(super) fn check_return_expr(&self, return_expr: &'tcx hir::Expr<'tcx>) { + /// `explicit_return` is `true` if we're checkng an explicit `return expr`, + /// and `false` if we're checking a trailing expression. + pub(super) fn check_return_expr( + &self, + return_expr: &'tcx hir::Expr<'tcx>, + explicit_return: bool, + ) { let ret_coercion = self.ret_coercion.as_ref().unwrap_or_else(|| { span_bug!(return_expr.span, "check_return_expr called outside fn body") }); let ret_ty = ret_coercion.borrow().expected_ty(); let return_expr_ty = self.check_expr_with_hint(return_expr, ret_ty); + let mut span = return_expr.span; + // Use the span of the trailing expression for our cause, + // not the span of the entire function + if !explicit_return { + if let ExprKind::Block(body, _) = return_expr.kind { + if let Some(last_expr) = body.expr { + span = last_expr.span; + } + } + } ret_coercion.borrow_mut().coerce( self, - &self.cause(return_expr.span, ObligationCauseCode::ReturnValue(return_expr.hir_id)), + &self.cause(span, ObligationCauseCode::ReturnValue(return_expr.hir_id)), return_expr, return_expr_ty, ); @@ -1844,6 +1860,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { field, expr_t, expr, + None, ); } err.emit(); @@ -1870,9 +1887,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let expr_snippet = self.tcx.sess.source_map().span_to_snippet(expr.span).unwrap_or(String::new()); - if expr_is_call && expr_snippet.starts_with("(") && expr_snippet.ends_with(")") { - let after_open = expr.span.lo() + rustc_span::BytePos(1); - let before_close = expr.span.hi() - rustc_span::BytePos(1); + let is_wrapped = expr_snippet.starts_with("(") && expr_snippet.ends_with(")"); + let after_open = expr.span.lo() + rustc_span::BytePos(1); + let before_close = expr.span.hi() - rustc_span::BytePos(1); + + if expr_is_call && is_wrapped { err.multipart_suggestion( "remove wrapping parentheses to call the method", vec![ @@ -1882,12 +1901,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Applicability::MachineApplicable, ); } else if !self.expr_in_place(expr.hir_id) { + // Suggest call parentheses inside the wrapping parentheses + let span = if is_wrapped { + expr.span.with_lo(after_open).with_hi(before_close) + } else { + expr.span + }; self.suggest_method_call( &mut err, "use parentheses to call the method", field, expr_t, expr, + Some(span), ); } else { err.help("methods are immutable and cannot be assigned to"); diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs index 9cf00bad10b..551522334aa 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs @@ -532,15 +532,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Some((variant, ty)) } else { - struct_span_err!( - self.tcx.sess, - path_span, - E0071, - "expected struct, variant or union type, found {}", - ty.sort_string(self.tcx) - ) - .span_label(path_span, "not a struct") - .emit(); + match ty.kind() { + ty::Error(_) => { + // E0071 might be caused by a spelling error, which will have + // already caused an error message and probably a suggestion + // elsewhere. Refrain from emitting more unhelpful errors here + // (issue #88844). + } + _ => { + struct_span_err!( + self.tcx.sess, + path_span, + E0071, + "expected struct, variant or union type, found {}", + ty.sort_string(self.tcx) + ) + .span_label(path_span, "not a struct") + .emit(); + } + } None } } diff --git a/compiler/rustc_typeck/src/check/intrinsic.rs b/compiler/rustc_typeck/src/check/intrinsic.rs index 664954b0eb7..ff7a26853b1 100644 --- a/compiler/rustc_typeck/src/check/intrinsic.rs +++ b/compiler/rustc_typeck/src/check/intrinsic.rs @@ -2,7 +2,7 @@ //! intrinsics that the compiler exposes. use crate::errors::{ - SimdShuffleMissingLength, UnrecognizedAtomicOperation, UnrecognizedIntrinsicFunction, + UnrecognizedAtomicOperation, UnrecognizedIntrinsicFunction, WrongNumberOfGenericArgumentsToIntrinsic, }; use crate::require_same_types; @@ -468,6 +468,7 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) | sym::simd_reduce_max | sym::simd_reduce_min_nanless | sym::simd_reduce_max_nanless => (2, vec![param(0)], param(1)), + sym::simd_shuffle => (3, vec![param(0), param(0), param(1)], param(2)), name if name.as_str().starts_with("simd_shuffle") => { match name.as_str()["simd_shuffle".len()..].parse() { Ok(n) => { @@ -475,7 +476,9 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) (2, params, param(1)) } Err(_) => { - tcx.sess.emit_err(SimdShuffleMissingLength { span: it.span, name }); + let msg = + format!("unrecognized platform-specific intrinsic function: `{}`", name); + tcx.sess.struct_span_err(it.span, &msg).emit(); return; } } diff --git a/compiler/rustc_typeck/src/check/method/mod.rs b/compiler/rustc_typeck/src/check/method/mod.rs index 2136d925423..8e09aa97dcf 100644 --- a/compiler/rustc_typeck/src/check/method/mod.rs +++ b/compiler/rustc_typeck/src/check/method/mod.rs @@ -141,6 +141,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { method_name: Ident, self_ty: Ty<'tcx>, call_expr: &hir::Expr<'_>, + span: Option<Span>, ) { let params = self .probe_for_name( @@ -159,7 +160,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .unwrap_or(0); // Account for `foo.bar<T>`; - let sugg_span = call_expr.span.shrink_to_hi(); + let sugg_span = span.unwrap_or_else(|| call_expr.span).shrink_to_hi(); let (suggestion, applicability) = ( format!("({})", (0..params).map(|_| "_").collect::<Vec<_>>().join(", ")), if params > 0 { Applicability::HasPlaceholders } else { Applicability::MaybeIncorrect }, diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index a056ab6aef2..829268e3cb5 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -1452,7 +1452,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { plural ), ); - if plural == "" { + + if unmentioned_fields.len() == 1 { let input = unmentioned_fields.iter().map(|(_, field)| field.name).collect::<Vec<_>>(); let suggested_name = find_best_match_for_name(&input, ident.name, None); @@ -1473,6 +1474,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // We don't want to throw `E0027` in case we have thrown `E0026` for them. unmentioned_fields.retain(|&(_, x)| x.name != suggested_name); } + } else if inexistent_fields.len() == 1 { + let unmentioned_field = unmentioned_fields[0].1.name; + err.span_suggestion_short( + ident.span, + &format!( + "`{}` has a field named `{}`", + tcx.def_path_str(variant.def_id), + unmentioned_field + ), + unmentioned_field.to_string(), + Applicability::MaybeIncorrect, + ); } } } diff --git a/compiler/rustc_typeck/src/errors.rs b/compiler/rustc_typeck/src/errors.rs index 1e6a240b2f8..47077779616 100644 --- a/compiler/rustc_typeck/src/errors.rs +++ b/compiler/rustc_typeck/src/errors.rs @@ -122,14 +122,6 @@ pub struct AssocTypeBindingNotAllowed { } #[derive(SessionDiagnostic)] -#[error = "E0439"] -pub struct SimdShuffleMissingLength { - #[message = "invalid `simd_shuffle`, needs length: `{name}`"] - pub span: Span, - pub name: Symbol, -} - -#[derive(SessionDiagnostic)] #[error = "E0436"] pub struct FunctionalRecordUpdateOnNonStruct { #[message = "functional record update syntax requires a struct"] diff --git a/compiler/rustc_typeck/src/impl_wf_check.rs b/compiler/rustc_typeck/src/impl_wf_check.rs index 194c4efdbb0..9b23bf241cc 100644 --- a/compiler/rustc_typeck/src/impl_wf_check.rs +++ b/compiler/rustc_typeck/src/impl_wf_check.rs @@ -58,9 +58,7 @@ pub fn impl_wf_check(tcx: TyCtxt<'_>) { // We will tag this as part of the WF check -- logically, it is, // but it's one that we must perform earlier than the rest of // WfCheck. - for &module in tcx.hir().krate().modules.keys() { - tcx.ensure().check_mod_impl_wf(module); - } + tcx.hir().for_each_module(|module| tcx.ensure().check_mod_impl_wf(module)) } fn check_mod_impl_wf(tcx: TyCtxt<'_>, module_def_id: LocalDefId) { diff --git a/compiler/rustc_typeck/src/lib.rs b/compiler/rustc_typeck/src/lib.rs index c703ca96ada..f8714cdc70c 100644 --- a/compiler/rustc_typeck/src/lib.rs +++ b/compiler/rustc_typeck/src/lib.rs @@ -473,9 +473,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorReported> { // FIXME(matthewjasper) We shouldn't need to use `track_errors`. tcx.sess.track_errors(|| { tcx.sess.time("type_collecting", || { - for &module in tcx.hir().krate().modules.keys() { - tcx.ensure().collect_mod_item_types(module); - } + tcx.hir().for_each_module(|module| tcx.ensure().collect_mod_item_types(module)) }); })?; @@ -505,9 +503,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorReported> { // NOTE: This is copy/pasted in librustdoc/core.rs and should be kept in sync. tcx.sess.time("item_types_checking", || { - for &module in tcx.hir().krate().modules.keys() { - tcx.ensure().check_mod_item_types(module); - } + tcx.hir().for_each_module(|module| tcx.ensure().check_mod_item_types(module)) }); tcx.sess.time("item_bodies_checking", || tcx.typeck_item_bodies(())); diff --git a/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs b/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs index bccc19774e0..7e69ad21d03 100644 --- a/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs +++ b/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs @@ -136,10 +136,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { AngleBrackets::Missing => 0, // Only lifetime arguments can be implied AngleBrackets::Implied => self.gen_args.args.len(), - AngleBrackets::Available => self.gen_args.args.iter().fold(0, |acc, arg| match arg { - hir::GenericArg::Lifetime(_) => acc + 1, - _ => acc, - }), + AngleBrackets::Available => self.gen_args.num_lifetime_params(), } } @@ -148,10 +145,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { AngleBrackets::Missing => 0, // Only lifetime arguments can be implied AngleBrackets::Implied => 0, - AngleBrackets::Available => self.gen_args.args.iter().fold(0, |acc, arg| match arg { - hir::GenericArg::Type(_) | hir::GenericArg::Const(_) => acc + 1, - _ => acc, - }), + AngleBrackets::Available => self.gen_args.num_generic_params(), } } @@ -651,7 +645,9 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { let mut found_redundant = false; for arg in self.gen_args.args { match arg { - hir::GenericArg::Type(_) | hir::GenericArg::Const(_) => { + hir::GenericArg::Type(_) + | hir::GenericArg::Const(_) + | hir::GenericArg::Infer(_) => { gen_arg_spans.push(arg.span()); if gen_arg_spans.len() > self.num_expected_type_or_const_args() { found_redundant = true; diff --git a/library/alloc/src/collections/vec_deque/into_iter.rs b/library/alloc/src/collections/vec_deque/into_iter.rs index 5f13c3bf303..54a157be0b9 100644 --- a/library/alloc/src/collections/vec_deque/into_iter.rs +++ b/library/alloc/src/collections/vec_deque/into_iter.rs @@ -17,7 +17,13 @@ pub struct IntoIter< T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, > { - pub(crate) inner: VecDeque<T, A>, + inner: VecDeque<T, A>, +} + +impl<T, A: Allocator> IntoIter<T, A> { + pub(super) fn new(inner: VecDeque<T, A>) -> Self { + IntoIter { inner } + } } #[stable(feature = "collection_debug", since = "1.17.0")] diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index e4b28204158..10144cc17bf 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -2827,7 +2827,7 @@ impl<T, A: Allocator> IntoIterator for VecDeque<T, A> { /// Consumes the `VecDeque` into a front-to-back iterator yielding elements by /// value. fn into_iter(self) -> IntoIter<T, A> { - IntoIter { inner: self } + IntoIter::new(self) } } diff --git a/library/core/src/lazy.rs b/library/core/src/lazy.rs index 2c517371c2c..e6bea462fa9 100644 --- a/library/core/src/lazy.rs +++ b/library/core/src/lazy.rs @@ -214,7 +214,16 @@ impl<T> OnceCell<T> { if let Some(val) = self.get() { return Ok(val); } - let val = f()?; + /// Avoid inlining the initialization closure into the common path that fetches + /// the already initialized value + #[cold] + fn outlined_call<F, T, E>(f: F) -> Result<T, E> + where + F: FnOnce() -> Result<T, E>, + { + f() + } + let val = outlined_call(f)?; // Note that *some* forms of reentrant initialization might lead to // UB (see `reentrant_init` test). I believe that just removing this // `assert`, while keeping `set/get` would be sound, but it seems diff --git a/library/core/src/panic.rs b/library/core/src/panic.rs index 463bec37265..7a8b04d6f3c 100644 --- a/library/core/src/panic.rs +++ b/library/core/src/panic.rs @@ -27,9 +27,14 @@ pub macro panic_2015 { ($msg:literal $(,)?) => ( $crate::panicking::panic($msg) ), + // Use `panic_str` instead of `panic_display::<&str>` for non_fmt_panic lint. ($msg:expr $(,)?) => ( $crate::panicking::panic_str($msg) ), + // Special-case the single-argument case for const_panic. + ("{}", $arg:expr $(,)?) => ( + $crate::panicking::panic_display(&$arg) + ), ($fmt:expr, $($arg:tt)+) => ( $crate::panicking::panic_fmt($crate::const_format_args!($fmt, $($arg)+)) ), @@ -44,6 +49,10 @@ pub macro panic_2021 { () => ( $crate::panicking::panic("explicit panic") ), + // Special-case the single-argument case for const_panic. + ("{}", $arg:expr $(,)?) => ( + $crate::panicking::panic_display(&$arg) + ), ($($t:tt)+) => ( $crate::panicking::panic_fmt($crate::const_format_args!($($t)+)) ), diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs index 02f32675247..a6aa4bf43c8 100644 --- a/library/core/src/panicking.rs +++ b/library/core/src/panicking.rs @@ -60,6 +60,13 @@ pub fn panic_str(expr: &str) -> ! { panic_fmt(format_args!("{}", expr)); } +#[inline] +#[track_caller] +#[cfg_attr(not(bootstrap), lang = "panic_display")] // needed for const-evaluated panics +pub fn panic_display<T: fmt::Display>(x: &T) -> ! { + panic_fmt(format_args!("{}", *x)); +} + #[cold] #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] #[track_caller] diff --git a/library/std/src/error.rs b/library/std/src/error.rs index ec9f0122950..8164ec56985 100644 --- a/library/std/src/error.rs +++ b/library/std/src/error.rs @@ -182,7 +182,7 @@ impl<'a, E: Error + 'a> From<E> for Box<dyn Error + 'a> { /// /// impl fmt::Display for AnError { /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - /// write!(f , "An error") + /// write!(f, "An error") /// } /// } /// @@ -215,7 +215,7 @@ impl<'a, E: Error + Send + Sync + 'a> From<E> for Box<dyn Error + Send + Sync + /// /// impl fmt::Display for AnError { /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - /// write!(f , "An error") + /// write!(f, "An error") /// } /// } /// diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 83c6ba0e6ea..f69baba9e73 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -234,6 +234,7 @@ #![feature(atomic_mut_ptr)] #![feature(auto_traits)] #![feature(bench_black_box)] +#![feature(bool_to_option)] #![feature(box_syntax)] #![feature(c_unwind)] #![feature(c_variadic)] @@ -258,6 +259,7 @@ #![feature(const_trait_impl)] #![feature(container_error_extra)] #![feature(core_intrinsics)] +#![feature(core_panic)] #![feature(custom_test_frameworks)] #![feature(decl_macro)] #![feature(doc_cfg)] diff --git a/library/std/src/os/linux/fs.rs b/library/std/src/os/linux/fs.rs index 9b7af97616c..9d18ccbeb24 100644 --- a/library/std/src/os/linux/fs.rs +++ b/library/std/src/os/linux/fs.rs @@ -1,4 +1,6 @@ -//! Linux-specific extensions to primitives in the `std::fs` module. +//! Linux-specific extensions to primitives in the [`std::fs`] module. +//! +//! [`std::fs`]: crate::fs #![stable(feature = "metadata_ext", since = "1.1.0")] diff --git a/library/std/src/os/linux/process.rs b/library/std/src/os/linux/process.rs index e3e7143c851..540363c0349 100644 --- a/library/std/src/os/linux/process.rs +++ b/library/std/src/os/linux/process.rs @@ -1,4 +1,6 @@ -//! Linux-specific extensions to primitives in the `std::process` module. +//! Linux-specific extensions to primitives in the [`std::process`] module. +//! +//! [`std::process`]: crate::process #![unstable(feature = "linux_pidfd", issue = "82971")] diff --git a/library/std/src/os/unix/ffi/mod.rs b/library/std/src/os/unix/ffi/mod.rs index c29df6596fd..5b49f50763d 100644 --- a/library/std/src/os/unix/ffi/mod.rs +++ b/library/std/src/os/unix/ffi/mod.rs @@ -1,4 +1,4 @@ -//! Unix-specific extension to the primitives in the `std::ffi` module. +//! Unix-specific extensions to primitives in the [`std::ffi`] module. //! //! # Examples //! @@ -31,6 +31,8 @@ //! let bytes = os_str.as_bytes(); //! assert_eq!(bytes, b"foo"); //! ``` +//! +//! [`std::ffi`]: crate::ffi #![stable(feature = "rust1", since = "1.0.0")] diff --git a/library/std/src/os/unix/fs.rs b/library/std/src/os/unix/fs.rs index 6cf37f23c57..0284a428b5d 100644 --- a/library/std/src/os/unix/fs.rs +++ b/library/std/src/os/unix/fs.rs @@ -1,10 +1,13 @@ -//! Unix-specific extensions to primitives in the `std::fs` module. +//! Unix-specific extensions to primitives in the [`std::fs`] module. +//! +//! [`std::fs`]: crate::fs #![stable(feature = "rust1", since = "1.0.0")] use super::platform::fs::MetadataExt as _; use crate::fs::{self, OpenOptions, Permissions}; use crate::io; +use crate::os::unix::io::{AsFd, AsRawFd}; use crate::path::Path; use crate::sys; use crate::sys_common::{AsInner, AsInnerMut, FromInner}; @@ -924,6 +927,75 @@ impl DirBuilderExt for fs::DirBuilder { } } +/// Change the owner and group of the specified path. +/// +/// Specifying either the uid or gid as `None` will leave it unchanged. +/// +/// Changing the owner typically requires privileges, such as root or a specific capability. +/// Changing the group typically requires either being the owner and a member of the group, or +/// having privileges. +/// +/// If called on a symbolic link, this will change the owner and group of the link target. To +/// change the owner and group of the link itself, see [`lchown`]. +/// +/// # Examples +/// +/// ```no_run +/// #![feature(unix_chown)] +/// use std::os::unix::fs; +/// +/// fn main() -> std::io::Result<()> { +/// fs::chown("/sandbox", Some(0), Some(0))?; +/// Ok(()) +/// } +/// ``` +#[unstable(feature = "unix_chown", issue = "88989")] +pub fn chown<P: AsRef<Path>>(dir: P, uid: Option<u32>, gid: Option<u32>) -> io::Result<()> { + sys::fs::chown(dir.as_ref(), uid.unwrap_or(u32::MAX), gid.unwrap_or(u32::MAX)) +} + +/// Change the owner and group of the file referenced by the specified open file descriptor. +/// +/// For semantics and required privileges, see [`chown`]. +/// +/// # Examples +/// +/// ```no_run +/// #![feature(unix_chown)] +/// use std::os::unix::fs; +/// +/// fn main() -> std::io::Result<()> { +/// let f = std::fs::File::open("/file")?; +/// fs::fchown(f, Some(0), Some(0))?; +/// Ok(()) +/// } +/// ``` +#[unstable(feature = "unix_chown", issue = "88989")] +pub fn fchown<F: AsFd>(fd: F, uid: Option<u32>, gid: Option<u32>) -> io::Result<()> { + sys::fs::fchown(fd.as_fd().as_raw_fd(), uid.unwrap_or(u32::MAX), gid.unwrap_or(u32::MAX)) +} + +/// Change the owner and group of the specified path, without dereferencing symbolic links. +/// +/// Identical to [`chown`], except that if called on a symbolic link, this will change the owner +/// and group of the link itself rather than the owner and group of the link target. +/// +/// # Examples +/// +/// ```no_run +/// #![feature(unix_chown)] +/// use std::os::unix::fs; +/// +/// fn main() -> std::io::Result<()> { +/// fs::lchown("/symlink", Some(0), Some(0))?; +/// Ok(()) +/// } +/// ``` +#[unstable(feature = "unix_chown", issue = "88989")] +pub fn lchown<P: AsRef<Path>>(dir: P, uid: Option<u32>, gid: Option<u32>) -> io::Result<()> { + sys::fs::lchown(dir.as_ref(), uid.unwrap_or(u32::MAX), gid.unwrap_or(u32::MAX)) +} + /// Change the root directory of the current process to the specified path. /// /// This typically requires privileges, such as root or a specific capability. diff --git a/library/std/src/os/unix/mod.rs b/library/std/src/os/unix/mod.rs index 17a02595724..62f750fa607 100644 --- a/library/std/src/os/unix/mod.rs +++ b/library/std/src/os/unix/mod.rs @@ -4,8 +4,8 @@ //! exposes Unix-specific functions that would otherwise be inappropriate as //! part of the core `std` library. //! -//! It exposes more ways to deal with platform-specific strings (`OsStr`, -//! `OsString`), allows to set permissions more granularly, extract low-level +//! It exposes more ways to deal with platform-specific strings ([`OsStr`], +//! [`OsString`]), allows to set permissions more granularly, extract low-level //! file descriptors from files and sockets, and has platform-specific helpers //! for spawning processes. //! @@ -24,6 +24,9 @@ //! Ok(()) //! } //! ``` +//! +//! [`OsStr`]: crate::ffi::OsStr +//! [`OsString`]: crate::ffi::OsString #![stable(feature = "rust1", since = "1.0.0")] #![doc(cfg(unix))] diff --git a/library/std/src/os/unix/net/mod.rs b/library/std/src/os/unix/net/mod.rs index d462bd4b5f7..8ce82208854 100644 --- a/library/std/src/os/unix/net/mod.rs +++ b/library/std/src/os/unix/net/mod.rs @@ -1,4 +1,4 @@ -//! Unix-specific networking functionality +//! Unix-specific networking functionality. #![stable(feature = "unix_socket", since = "1.10.0")] diff --git a/library/std/src/os/unix/process.rs b/library/std/src/os/unix/process.rs index 650dcbabbae..4d23805e479 100644 --- a/library/std/src/os/unix/process.rs +++ b/library/std/src/os/unix/process.rs @@ -1,4 +1,6 @@ -//! Unix-specific extensions to primitives in the `std::process` module. +//! Unix-specific extensions to primitives in the [`std::process`] module. +//! +//! [`std::process`]: crate::process #![stable(feature = "rust1", since = "1.0.0")] diff --git a/library/std/src/os/unix/thread.rs b/library/std/src/os/unix/thread.rs index 7221da1a9a7..03dcc3a4f9b 100644 --- a/library/std/src/os/unix/thread.rs +++ b/library/std/src/os/unix/thread.rs @@ -1,4 +1,6 @@ -//! Unix-specific extensions to primitives in the `std::thread` module. +//! Unix-specific extensions to primitives in the [`std::thread`] module. +//! +//! [`std::thread`]: crate::thread #![stable(feature = "thread_extensions", since = "1.9.0")] diff --git a/library/std/src/os/wasi/ffi.rs b/library/std/src/os/wasi/ffi.rs index 17e12a395a6..41dd8702e98 100644 --- a/library/std/src/os/wasi/ffi.rs +++ b/library/std/src/os/wasi/ffi.rs @@ -1,4 +1,6 @@ -//! WASI-specific extension to the primitives in the `std::ffi` module +//! WASI-specific extensions to primitives in the [`std::ffi`] module +//! +//! [`std::ffi`]: crate::ffi #![stable(feature = "rust1", since = "1.0.0")] diff --git a/library/std/src/os/wasi/fs.rs b/library/std/src/os/wasi/fs.rs index 3df27563e21..907368061d7 100644 --- a/library/std/src/os/wasi/fs.rs +++ b/library/std/src/os/wasi/fs.rs @@ -1,4 +1,6 @@ -//! WASI-specific extensions to primitives in the `std::fs` module. +//! WASI-specific extensions to primitives in the [`std::fs`] module. +//! +//! [`std::fs`]: crate::fs #![deny(unsafe_op_in_unsafe_fn)] #![unstable(feature = "wasi_ext", issue = "71213")] diff --git a/library/std/src/os/wasi/mod.rs b/library/std/src/os/wasi/mod.rs index d767c149dc5..bbaf328f457 100644 --- a/library/std/src/os/wasi/mod.rs +++ b/library/std/src/os/wasi/mod.rs @@ -24,6 +24,9 @@ //! Ok(()) //! } //! ``` +//! +//! [`OsStr`]: crate::ffi::OsStr +//! [`OsString`]: crate::ffi::OsString #![stable(feature = "rust1", since = "1.0.0")] #![deny(unsafe_op_in_unsafe_fn)] diff --git a/library/std/src/os/windows/ffi.rs b/library/std/src/os/windows/ffi.rs index 8d29fa7d66f..a9493a94cac 100644 --- a/library/std/src/os/windows/ffi.rs +++ b/library/std/src/os/windows/ffi.rs @@ -1,4 +1,4 @@ -//! Windows-specific extensions to the primitives in the `std::ffi` module. +//! Windows-specific extensions to primitives in the [`std::ffi`] module. //! //! # Overview //! @@ -49,6 +49,7 @@ //! [ill-formed-utf-16]: https://simonsapin.github.io/wtf-8/#ill-formed-utf-16 //! [`collect`]: crate::iter::Iterator::collect //! [U+FFFD]: crate::char::REPLACEMENT_CHARACTER +//! [`std::ffi`]: crate::ffi #![stable(feature = "rust1", since = "1.0.0")] diff --git a/library/std/src/os/windows/fs.rs b/library/std/src/os/windows/fs.rs index 71563a02dcb..be35ab0ca1e 100644 --- a/library/std/src/os/windows/fs.rs +++ b/library/std/src/os/windows/fs.rs @@ -1,4 +1,6 @@ -//! Windows-specific extensions for the primitives in the `std::fs` module. +//! Windows-specific extensions to primitives in the [`std::fs`] module. +//! +//! [`std::fs`]: crate::fs #![stable(feature = "rust1", since = "1.0.0")] diff --git a/library/std/src/os/windows/mod.rs b/library/std/src/os/windows/mod.rs index 969054dd3b3..52eb3b7c067 100644 --- a/library/std/src/os/windows/mod.rs +++ b/library/std/src/os/windows/mod.rs @@ -5,6 +5,22 @@ //! the core `std` library. These extensions allow developers to use //! `std` types and idioms with Windows in a way that the normal //! platform-agnostic idioms would not normally support. +//! +//! # Examples +//! +//! ```no_run +//! use std::fs::File; +//! use std::os::windows::prelude::*; +//! +//! fn main() -> std::io::Result<()> { +//! let f = File::create("foo.txt")?; +//! let handle = f.as_raw_handle(); +//! +//! // use handle with native windows bindings +//! +//! Ok(()) +//! } +//! ``` #![stable(feature = "rust1", since = "1.0.0")] #![doc(cfg(windows))] diff --git a/library/std/src/os/windows/process.rs b/library/std/src/os/windows/process.rs index b246599dfc0..9510d104806 100644 --- a/library/std/src/os/windows/process.rs +++ b/library/std/src/os/windows/process.rs @@ -1,4 +1,6 @@ -//! Extensions to `std::process` for Windows. +//! Windows-specific extensions to primitives in the [`std::process`] module. +//! +//! [`std::process`]: crate::process #![stable(feature = "process_extensions", since = "1.2.0")] diff --git a/library/std/src/os/windows/thread.rs b/library/std/src/os/windows/thread.rs index fb1bf66ceed..d81d6d0ac28 100644 --- a/library/std/src/os/windows/thread.rs +++ b/library/std/src/os/windows/thread.rs @@ -1,4 +1,6 @@ -//! Extensions to `std::thread` for Windows. +//! Windows-specific extensions to primitives in the [`std::thread`] module. +//! +//! [`std::thread`]: crate::thread #![stable(feature = "thread_extensions", since = "1.9.0")] diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs index c1c03958497..21e9669c110 100644 --- a/library/std/src/panic.rs +++ b/library/std/src/panic.rs @@ -10,7 +10,7 @@ use crate::thread::Result; #[doc(hidden)] #[unstable(feature = "edition_panic", issue = "none", reason = "use panic!() instead")] -#[allow_internal_unstable(libstd_sys_internals, const_format_args)] +#[allow_internal_unstable(libstd_sys_internals, const_format_args, core_panic)] #[cfg_attr(not(test), rustc_diagnostic_item = "std_panic_2015_macro")] #[rustc_macro_transparency = "semitransparent"] pub macro panic_2015 { @@ -20,6 +20,10 @@ pub macro panic_2015 { ($msg:expr $(,)?) => ({ $crate::rt::begin_panic($msg) }), + // Special-case the single-argument case for const_panic. + ("{}", $arg:expr $(,)?) => ({ + $crate::rt::panic_display(&$arg) + }), ($fmt:expr, $($arg:tt)+) => ({ $crate::rt::begin_panic_fmt(&$crate::const_format_args!($fmt, $($arg)+)) }), diff --git a/library/std/src/rt.rs b/library/std/src/rt.rs index 72e6c23ee49..893167e3730 100644 --- a/library/std/src/rt.rs +++ b/library/std/src/rt.rs @@ -16,6 +16,7 @@ // Re-export some of our utilities which are expected by other crates. pub use crate::panicking::{begin_panic, begin_panic_fmt, panic_count}; +pub use core::panicking::panic_display; // To reduce the generated code of the new `lang_start`, this function is doing // the real work. @@ -59,10 +60,10 @@ fn lang_start<T: crate::process::Termination + 'static>( argc: isize, argv: *const *const u8, ) -> isize { - lang_start_internal( + let Ok(v) = lang_start_internal( &move || crate::sys_common::backtrace::__rust_begin_short_backtrace(main).report(), argc, argv, - ) - .into_ok() + ); + v } diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs index 6d7524a733a..a4fff9b2e64 100644 --- a/library/std/src/sys/unix/fs.rs +++ b/library/std/src/sys/unix/fs.rs @@ -1416,6 +1416,23 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> { Ok(bytes_copied as u64) } +pub fn chown(path: &Path, uid: u32, gid: u32) -> io::Result<()> { + let path = cstr(path)?; + cvt(unsafe { libc::chown(path.as_ptr(), uid as libc::uid_t, gid as libc::gid_t) })?; + Ok(()) +} + +pub fn fchown(fd: c_int, uid: u32, gid: u32) -> io::Result<()> { + cvt(unsafe { libc::fchown(fd, uid as libc::uid_t, gid as libc::gid_t) })?; + Ok(()) +} + +pub fn lchown(path: &Path, uid: u32, gid: u32) -> io::Result<()> { + let path = cstr(path)?; + cvt(unsafe { libc::lchown(path.as_ptr(), uid as libc::uid_t, gid as libc::gid_t) })?; + Ok(()) +} + #[cfg(not(any(target_os = "fuchsia", target_os = "vxworks")))] pub fn chroot(dir: &Path) -> io::Result<()> { let dir = cstr(dir)?; diff --git a/library/std/src/time/monotonic.rs b/library/std/src/time/monotonic.rs index fa96b7abff6..198ae739b55 100644 --- a/library/std/src/time/monotonic.rs +++ b/library/std/src/time/monotonic.rs @@ -37,35 +37,36 @@ pub mod inner { // This could be a problem for programs that call instants at intervals greater // than 68 years. Interstellar probes may want to ensure that actually_monotonic() is true. let packed = (secs << 32) | nanos; - let old = mono.load(Relaxed); - - if old == UNINITIALIZED || packed.wrapping_sub(old) < u64::MAX / 2 { - mono.store(packed, Relaxed); - raw - } else { - // Backslide occurred. We reconstruct monotonized time from the upper 32 bit of the - // passed in value and the 64bits loaded from the atomic - let seconds_lower = old >> 32; - let mut seconds_upper = secs & 0xffff_ffff_0000_0000; - if secs & 0xffff_ffff > seconds_lower { - // Backslide caused the lower 32bit of the seconds part to wrap. - // This must be the case because the seconds part is larger even though - // we are in the backslide branch, i.e. the seconds count should be smaller or equal. - // - // We assume that backslides are smaller than 2^32 seconds - // which means we need to add 1 to the upper half to restore it. - // - // Example: - // most recent observed time: 0xA1_0000_0000_0000_0000u128 - // bits stored in AtomicU64: 0x0000_0000_0000_0000u64 - // backslide by 1s - // caller time is 0xA0_ffff_ffff_0000_0000u128 - // -> we can fix up the upper half time by adding 1 << 32 - seconds_upper = seconds_upper.wrapping_add(0x1_0000_0000); + let updated = mono.fetch_update(Relaxed, Relaxed, |old| { + (old == UNINITIALIZED || packed.wrapping_sub(old) < u64::MAX / 2).then_some(packed) + }); + match updated { + Ok(_) => raw, + Err(newer) => { + // Backslide occurred. We reconstruct monotonized time from the upper 32 bit of the + // passed in value and the 64bits loaded from the atomic + let seconds_lower = newer >> 32; + let mut seconds_upper = secs & 0xffff_ffff_0000_0000; + if secs & 0xffff_ffff > seconds_lower { + // Backslide caused the lower 32bit of the seconds part to wrap. + // This must be the case because the seconds part is larger even though + // we are in the backslide branch, i.e. the seconds count should be smaller or equal. + // + // We assume that backslides are smaller than 2^32 seconds + // which means we need to add 1 to the upper half to restore it. + // + // Example: + // most recent observed time: 0xA1_0000_0000_0000_0000u128 + // bits stored in AtomicU64: 0x0000_0000_0000_0000u64 + // backslide by 1s + // caller time is 0xA0_ffff_ffff_0000_0000u128 + // -> we can fix up the upper half time by adding 1 << 32 + seconds_upper = seconds_upper.wrapping_add(0x1_0000_0000); + } + let secs = seconds_upper | seconds_lower; + let nanos = newer as u32; + ZERO.checked_add_duration(&Duration::new(secs, nanos)).unwrap() } - let secs = seconds_upper | seconds_lower; - let nanos = old as u32; - ZERO.checked_add_duration(&Duration::new(secs, nanos)).unwrap() } } } diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index b7478d83955..af3774b7c75 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -537,7 +537,7 @@ impl Step for Rustc { fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { let builder = run.builder; - run.krate("rustc-main").default_condition(builder.config.docs) + run.krate("rustc-main").path("compiler").default_condition(builder.config.docs) } fn make_run(run: RunConfig<'_>) { @@ -553,9 +553,24 @@ impl Step for Rustc { fn run(self, builder: &Builder<'_>) { let stage = self.stage; let target = self.target; + let mut is_explicit_request = false; builder.info(&format!("Documenting stage{} compiler ({})", stage, target)); - if !builder.config.compiler_docs { + let paths = builder + .paths + .iter() + .map(components_simplified) + .filter_map(|path| { + if path.get(0) == Some(&"compiler") { + is_explicit_request = true; + path.get(1).map(|p| p.to_owned()) + } else { + None + } + }) + .collect::<Vec<_>>(); + + if !builder.config.compiler_docs && !is_explicit_request { builder.info("\tskipping - compiler/librustdoc docs disabled"); return; } @@ -604,26 +619,54 @@ impl Step for Rustc { cargo.rustdocflag("--extern-html-root-url"); cargo.rustdocflag("ena=https://docs.rs/ena/latest/"); - // Find dependencies for top level crates. let mut compiler_crates = HashSet::new(); - for root_crate in &["rustc_driver", "rustc_codegen_llvm", "rustc_codegen_ssa"] { - compiler_crates.extend( - builder - .in_tree_crates(root_crate, Some(target)) - .into_iter() - .map(|krate| krate.name), - ); + + if paths.is_empty() { + // Find dependencies for top level crates. + for root_crate in &["rustc_driver", "rustc_codegen_llvm", "rustc_codegen_ssa"] { + compiler_crates.extend( + builder + .in_tree_crates(root_crate, Some(target)) + .into_iter() + .map(|krate| krate.name), + ); + } + } else { + for root_crate in paths { + if !builder.src.join("compiler").join(&root_crate).exists() { + builder.info(&format!( + "\tskipping - compiler/{} (unknown compiler crate)", + root_crate + )); + } else { + compiler_crates.extend( + builder + .in_tree_crates(root_crate, Some(target)) + .into_iter() + .map(|krate| krate.name), + ); + } + } } + let mut to_open = None; for krate in &compiler_crates { // Create all crate output directories first to make sure rustdoc uses // relative links. // FIXME: Cargo should probably do this itself. t!(fs::create_dir_all(out_dir.join(krate))); cargo.arg("-p").arg(krate); + if to_open.is_none() { + to_open = Some(krate); + } } builder.run(&mut cargo.into()); + // Let's open the first crate documentation page: + if let Some(krate) = to_open { + let index = out.join(krate).join("index.html"); + open(builder, &index); + } } } diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index d86b3b785d1..765c77d5646 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -329,18 +329,14 @@ crate fn run_global_ctxt( // NOTE: This is copy/pasted from typeck/lib.rs and should be kept in sync with those changes. tcx.sess.time("item_types_checking", || { - for &module in tcx.hir().krate().modules.keys() { - tcx.ensure().check_mod_item_types(module); - } + tcx.hir().for_each_module(|module| tcx.ensure().check_mod_item_types(module)) }); tcx.sess.abort_if_errors(); tcx.sess.time("missing_docs", || { rustc_lint::check_crate(tcx, rustc_lint::builtin::MissingDoc::new); }); tcx.sess.time("check_mod_attrs", || { - for &module in tcx.hir().krate().modules.keys() { - tcx.ensure().check_mod_attrs(module); - } + tcx.hir().for_each_module(|module| tcx.ensure().check_mod_attrs(module)) }); rustc_passes::stability::check_unused_or_stable_features(tcx); diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index 1dd0917699b..c1a83ad5820 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -268,10 +268,18 @@ pub(super) fn write_shared( // Maybe we can change the representation to move this out of main.js? write_minify( "main.js", - static_files::MAIN_JS.replace( - "/* INSERT THEMES HERE */", - &format!(" = {}", serde_json::to_string(&themes).unwrap()), - ), + static_files::MAIN_JS + .replace( + "/* INSERT THEMES HERE */", + &format!(" = {}", serde_json::to_string(&themes).unwrap()), + ) + .replace( + "/* INSERT RUSTDOC_VERSION HERE */", + &format!( + "rustdoc {}", + rustc_interface::util::version_str().unwrap_or("unknown version") + ), + ), cx, options, )?; diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 2d4bfc62af6..eb7cc9309f4 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -928,15 +928,24 @@ body.blur > :not(#help) { display: block; margin-right: 0.5rem; } -#help > div > span { +#help span.top, #help span.bottom { text-align: center; display: block; - margin: 10px 0; font-size: 18px; - border-bottom: 1px solid #ccc; + +} +#help span.top { + text-align: center; + display: block; + margin: 10px 0; + border-bottom: 1px solid; padding-bottom: 4px; margin-bottom: 6px; } +#help span.bottom { + clear: both; + border-top: 1px solid; +} #help dd { margin: 5px 35px; } #help .infos { padding-left: 0; } #help h1, #help h2 { margin-top: 0; } diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css index eada8f4a04d..c79801e8308 100644 --- a/src/librustdoc/html/static/css/themes/ayu.css +++ b/src/librustdoc/html/static/css/themes/ayu.css @@ -286,8 +286,8 @@ details.undocumented > summary::before { border-radius: 4px; } -#help > div > span { - border-bottom-color: #5c6773; +#help span.bottom, #help span.top { + border-color: #5c6773; } .since { diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css index d9348be6994..d2e54070acd 100644 --- a/src/librustdoc/html/static/css/themes/dark.css +++ b/src/librustdoc/html/static/css/themes/dark.css @@ -242,8 +242,8 @@ details.undocumented > summary::before { border-color: #bfbfbf; } -#help > div > span { - border-bottom-color: #bfbfbf; +#help span.bottom, #help span.top { + border-color: #bfbfbf; } #help dt { diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css index 0ffe5929ea5..25d810560c1 100644 --- a/src/librustdoc/html/static/css/themes/light.css +++ b/src/librustdoc/html/static/css/themes/light.css @@ -232,8 +232,8 @@ details.undocumented > summary::before { border-color: #bfbfbf; } -#help > div > span { - border-bottom-color: #bfbfbf; +#help span.bottom, #help span.top { + border-color: #bfbfbf; } .since { diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 1eebd392564..e396fd9d288 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -911,6 +911,7 @@ function hideThemeButtonState() { }); var book_info = document.createElement("span"); + book_info.className = "top"; book_info.innerHTML = "You can find more information in \ <a href=\"https://doc.rust-lang.org/rustdoc/\">the rustdoc book</a>."; @@ -961,6 +962,14 @@ function hideThemeButtonState() { container.appendChild(div_shortcuts); container.appendChild(div_infos); + var rustdoc_version = document.createElement("span"); + rustdoc_version.className = "bottom"; + var rustdoc_version_code = document.createElement("code"); + rustdoc_version_code.innerText = "/* INSERT RUSTDOC_VERSION HERE */"; + rustdoc_version.appendChild(rustdoc_version_code); + + container.appendChild(rustdoc_version); + popup.appendChild(container); insertAfter(popup, searchState.outputElement()); // So that it's only built once and then it'll do nothing when called! diff --git a/src/test/debuginfo/basic-types.rs b/src/test/debuginfo/basic-types.rs index d300e374bec..c8879856b96 100644 --- a/src/test/debuginfo/basic-types.rs +++ b/src/test/debuginfo/basic-types.rs @@ -9,10 +9,6 @@ // This fails on lldb 6.0.1 on x86-64 Fedora 28; so ignore Linux for now. // ignore-linux -// This started failing in windows too. See https://github.com/rust-lang/rust/issues/88796 -// FIXME: fix and unignore this on windows -// ignore-windows - // compile-flags:-g // === GDB TESTS =================================================================================== @@ -132,8 +128,9 @@ // cdb-command:dx f64 // cdb-check:f64 : 3.500000 [Type: double] // cdb-command:.enable_unicode 1 +// FIXME(#88840): The latest version of the Windows SDK broke the visualizer for str. // cdb-command:dx s -// cdb-check:s : "Hello, World!" [Type: str] +// cdb-check:s : [...] [Type: str] #![allow(unused_variables)] #![feature(omit_gdb_pretty_printer_section)] diff --git a/src/test/debuginfo/msvc-pretty-enums.rs b/src/test/debuginfo/msvc-pretty-enums.rs index 67b5da510f8..642694355ad 100644 --- a/src/test/debuginfo/msvc-pretty-enums.rs +++ b/src/test/debuginfo/msvc-pretty-enums.rs @@ -1,67 +1,45 @@ // only-cdb -// ignore-tidy-linelength // compile-flags:-g -// This started failing recently. See https://github.com/rust-lang/rust/issues/88796 -// FIXME: fix and unignore this -// ignore-windows - // cdb-command: g -// Note: The natvis used to visualize niche-layout enums don't work correctly in cdb -// so the best we can do is to make sure we are generating the right debuginfo. -// Therefore, we use the `!` [format specifier](https://docs.microsoft.com/en-us/visualstudio/debugger/format-specifiers-in-cpp?view=vs-2019#BKMK_Visual_Studio_2012_format_specifiers) -// to disable the natvis for a given expression. We also provide the `-r2` flag -// to expand the expression 2 levels. - -// cdb-command: dx -r2 a,! -// cdb-check:a,! [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum> >, 2, 16, Some>] -// cdb-check: [+0x000] dataful_variant [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum> >, 2, 16, Some>::Some] -// cdb-check: [+0x000] __0 : Low (0x2) [Type: msvc_pretty_enums::CStyleEnum] -// cdb-check: [+0x000] discriminant : 0x2 [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum> >, 2, 16, Some>::Discriminant$] - -// cdb-command: dx -r2 b,! -// cdb-check:b,! [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum> >, 2, 16, Some>] -// cdb-check: [+0x000] dataful_variant [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum> >, 2, 16, Some>::Some] -// cdb-check: [+0x000] __0 : 0x11 [Type: msvc_pretty_enums::CStyleEnum] -// cdb-check: [+0x000] discriminant : None (0x11) [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum> >, 2, 16, Some>::Discriminant$] - -// cdb-command: dx -r2 c,! -// cdb-check:c,! [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>] -// cdb-check: [+0x000] dataful_variant [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>::Data] -// cdb-check: [+0x000] my_data : 0x11 [Type: msvc_pretty_enums::CStyleEnum] -// cdb-check: [+0x000] discriminant : Tag1 (0x11) [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>::Discriminant$] - -// cdb-command: dx -r2 d,! -// cdb-check:d,! [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>] -// cdb-check: [+0x000] dataful_variant [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>::Data] -// cdb-check: [+0x000] my_data : High (0x10) [Type: msvc_pretty_enums::CStyleEnum] -// cdb-check: [+0x000] discriminant : 0x10 [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>::Discriminant$] - -// cdb-command: dx -r2 e,! -// cdb-check:e,! [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>] -// cdb-check: [+0x000] dataful_variant [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>::Data] -// cdb-check: [+0x000] my_data : 0x13 [Type: msvc_pretty_enums::CStyleEnum] -// cdb-check: [+0x000] discriminant : Tag2 (0x13) [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>::Discriminant$] - -// cdb-command: dx -r2 f,! -// cdb-check:f,! [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>] -// cdb-check: [+0x000] dataful_variant [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>::Some] -// cdb-check: [+0x000] __0 : 0x[...] : 0x1 [Type: unsigned int *] -// cdb-check: [+0x000] discriminant : 0x[...] [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>::Discriminant$] - -// cdb-command: dx -r2 g,! -// cdb-check:g,! [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>] -// cdb-check: [+0x000] dataful_variant [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>::Some] -// cdb-check: [+0x000] __0 : 0x0 [Type: unsigned int *] -// cdb-check: [+0x000] discriminant : None (0x0) [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>::Discriminant$] - -// cdb-command: dx -r2 h,! -// cdb-check:h,! : Some [Type: enum$<core::option::Option<u32> >] -// cdb-check: [+0x000] variant0 [Type: enum$<core::option::Option<u32> >::None] -// cdb-check: [+0x000] variant1 [Type: enum$<core::option::Option<u32> >::Some] -// cdb-check: [+0x004] __0 : 0xc [Type: unsigned int] -// cdb-check: [+0x000] discriminant : Some (0x1) [Type: core::option::Option] +// cdb-command: dx a +// cdb-check:a : Some({...}) [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum> >, 2, 16, Some>] +// cdb-check: [<Raw View>] [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum> >, 2, 16, Some>] +// cdb-check: [variant] : Some +// cdb-check: [+0x000] __0 : Low (0x2) [Type: msvc_pretty_enums::CStyleEnum] + +// cdb-command: dx b +// cdb-check:b : None [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum> >, 2, 16, Some>] +// cdb-check: [<Raw View>] [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum> >, 2, 16, Some>] +// cdb-check: [variant] : None + +// cdb-command: dx c +// cdb-check:c : Tag1 [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>] +// cdb-check: [<Raw View>] [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>] +// cdb-check: [variant] : Tag1 + +// cdb-command: dx d +// cdb-check:d : Data({...}) [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>] +// cdb-check: [<Raw View>] [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>] +// cdb-check: [variant] : Data +// cdb-check: [+0x000] my_data : High (0x10) [Type: msvc_pretty_enums::CStyleEnum] + +// cdb-command: dx e +// cdb-check:e : Tag2 [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>] +// cdb-check: [<Raw View>] [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>] +// cdb-check: [variant] : Tag2 + +// cdb-command: dx f +// cdb-check:f : Some({...}) [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>] +// cdb-check: [<Raw View>] [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>] +// cdb-check: [variant] : Some +// cdb-check: [+0x000] __0 : 0x[...] : 0x1 [Type: unsigned int *] + +// cdb-command: dx g +// cdb-check:g : None [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>] +// cdb-check: [<Raw View>] [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>] +// cdb-check: [variant] : None // cdb-command: dx h // cdb-check:h : Some [Type: enum$<core::option::Option<u32> >] @@ -69,13 +47,6 @@ // cdb-check: [variant] : Some // cdb-check: [+0x004] __0 : 0xc [Type: unsigned int] -// cdb-command: dx -r2 i,! -// cdb-check:i,! : None [Type: enum$<core::option::Option<u32> >] -// cdb-check: [+0x000] variant0 [Type: enum$<core::option::Option<u32> >::None] -// cdb-check: [+0x000] variant1 [Type: enum$<core::option::Option<u32> >::Some] -// cdb-check: [+0x004] __0 : 0x[...] [Type: unsigned int] -// cdb-check: [+0x000] discriminant : None (0x0) [Type: core::option::Option] - // cdb-command: dx i // cdb-check:i : None [Type: enum$<core::option::Option<u32> >] // cdb-check: [<Raw View>] [Type: enum$<core::option::Option<u32> >] @@ -84,16 +55,17 @@ // cdb-command: dx j // cdb-check:j : High (0x10) [Type: msvc_pretty_enums::CStyleEnum] -// cdb-command: dx -r2 k,! -// cdb-check:k,! [Type: enum$<core::option::Option<alloc::string::String>, 1, [...], Some>] -// cdb-check: [+0x000] dataful_variant [Type: enum$<core::option::Option<alloc::string::String>, 1, [...], Some>::Some] -// cdb-check: [+0x000] __0 [Type: alloc::string::String] -// cdb-check: [+0x000] discriminant : 0x[...] [Type: enum$<core::option::Option<alloc::string::String>, 1, [...], Some>::Discriminant$] - -// cdb-command: dx -r2 l,! -// cdb-check:l,! : $T2 [Type: enum$<core::result::Result<u32,enum$<msvc_pretty_enums::Empty> >, Ok>] -// cdb-check: [+0x000] Ok [Type: enum$<core::result::Result<u32,enum$<msvc_pretty_enums::Empty> >, Ok>::Ok] -// cdb-check: [+0x000] __0 : 0x2a [Type: unsigned int] +// cdb-command: dx k +// cdb-check:k : Some({...}) [Type: enum$<core::option::Option<alloc::string::String>, 1, [...], Some>] +// cdb-check: [<Raw View>] [Type: enum$<core::option::Option<alloc::string::String>, 1, [...], Some>] +// cdb-check: [variant] : Some +// cdb-check: [+0x000] __0 : "IAMA optional string!" [Type: alloc::string::String] + +// cdb-command: dx l +// cdb-check:l : Ok [Type: enum$<core::result::Result<u32,enum$<msvc_pretty_enums::Empty> >, Ok>] +// cdb-check: [<Raw View>] [Type: enum$<core::result::Result<u32,enum$<msvc_pretty_enums::Empty> >, Ok>] +// cdb-check: [variant] : Ok +// cdb-check: [+0x000] __0 : 0x2a [Type: unsigned int] pub enum CStyleEnum { Low = 2, diff --git a/src/test/debuginfo/pretty-std.rs b/src/test/debuginfo/pretty-std.rs index cb2e6c618b1..55a4ecc1c1a 100644 --- a/src/test/debuginfo/pretty-std.rs +++ b/src/test/debuginfo/pretty-std.rs @@ -6,10 +6,6 @@ // min-lldb-version: 310 // min-cdb-version: 10.0.18317.1001 -// This started failing recently. See https://github.com/rust-lang/rust/issues/88796 -// FIXME: fix and unignore this -// ignore-windows - // === GDB TESTS =================================================================================== // gdb-command: run @@ -115,9 +111,11 @@ // cdb-check: [11] : 33 '!' [Type: char] // cdb-command: dx os_string -// cdb-check:os_string : "IAMA OS string 😃" [Type: std::ffi::os_str::OsString] +// NOTE: OSString is WTF-8 encoded which Windows debuggers don't understand. Verify the UTF-8 +// portion displays correctly. +// cdb-check:os_string : "IAMA OS string [...]" [Type: std::ffi::os_str::OsString] // cdb-check: [<Raw View>] [Type: std::ffi::os_str::OsString] -// cdb-check: [chars] : "IAMA OS string 😃" +// cdb-check: [chars] : "IAMA OS string [...]" // cdb-command: dx some // cdb-check:some : Some [Type: enum$<core::option::Option<i16> >] @@ -131,8 +129,10 @@ // cdb-check: [variant] : None // cdb-command: dx some_string -// NOTE: cdb fails to interpret debug info of Option enums on i686. -// cdb-check:some_string [Type: enum$<core::option::Option<alloc::string::String>, 1, [...], Some>] +// cdb-check:some_string : Some({...}) [Type: enum$<core::option::Option<alloc::string::String>, 1, [...], Some>] +// cdb-check: [<Raw View>] [Type: enum$<core::option::Option<alloc::string::String>, 1, [...], Some>] +// cdb-check: [variant] : Some +// cdb-check: [+0x000] __0 : "IAMA optional string!" [Type: alloc::string::String] // cdb-command: dx linkedlist // cdb-check:linkedlist : { len=0x2 } [Type: alloc::collections::linked_list::LinkedList<i32>] diff --git a/src/test/mir-opt/coverage_graphviz.main.InstrumentCoverage.0.dot b/src/test/mir-opt/coverage_graphviz.main.InstrumentCoverage.0.dot index eeedbb215c0..ca0eb7e845a 100644 --- a/src/test/mir-opt/coverage_graphviz.main.InstrumentCoverage.0.dot +++ b/src/test/mir-opt/coverage_graphviz.main.InstrumentCoverage.0.dot @@ -2,10 +2,12 @@ digraph Cov_0_3 { graph [fontname="Courier, monospace"]; node [fontname="Courier, monospace"]; edge [fontname="Courier, monospace"]; - bcb2__Cov_0_3 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">bcb2</td></tr><tr><td align="left" balign="left">Expression(bcb0 - bcb1) at 13:10-13:10<br/> 13:10-13:10: @4[0]: Coverage::Expression(4294967295) = 1 - 2 for $DIR/coverage_graphviz.rs:13:10 - 13:11</td></tr><tr><td align="left" balign="left">bb4: Goto</td></tr></table>>]; - bcb1__Cov_0_3 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">bcb1</td></tr><tr><td align="left" balign="left">Counter(bcb1) at 12:13-12:18<br/> 12:13-12:18: @3[0]: Coverage::Expression(4294967294) = 2 + 0 for $DIR/coverage_graphviz.rs:15:1 - 15:2<br/>Expression(bcb1 + 0) at 15:2-15:2<br/> 15:2-15:2: @3.Return: return</td></tr><tr><td align="left" balign="left">bb3: Return</td></tr></table>>]; - bcb0__Cov_0_3 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">bcb0</td></tr><tr><td align="left" balign="left"></td></tr><tr><td align="left" balign="left">Counter(bcb0) at 9:1-11:17<br/> 11:12-11:17: @1.Call: _2 = bar() -> [return: bb2, unwind: bb5]</td></tr><tr><td align="left" balign="left">bb0: FalseUnwind<br/>bb1: Call</td></tr><tr><td align="left" balign="left">bb2: SwitchInt</td></tr></table>>]; - bcb2__Cov_0_3 -> bcb0__Cov_0_3 [label=<>]; - bcb0__Cov_0_3 -> bcb2__Cov_0_3 [label=<false>]; - bcb0__Cov_0_3 -> bcb1__Cov_0_3 [label=<otherwise>]; + bcb3__Cov_0_3 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">bcb3</td></tr><tr><td align="left" balign="left">Counter(bcb3) at 13:10-13:10<br/> 13:10-13:10: @5[0]: Coverage::Counter(2) for $DIR/coverage_graphviz.rs:13:10 - 13:11</td></tr><tr><td align="left" balign="left">bb5: Goto</td></tr></table>>]; + bcb2__Cov_0_3 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">bcb2</td></tr><tr><td align="left" balign="left">Expression(bcb1:(bcb0 + bcb3) - bcb3) at 12:13-12:18<br/> 12:13-12:18: @4[0]: Coverage::Expression(4294967293) = 4294967294 + 0 for $DIR/coverage_graphviz.rs:15:1 - 15:2<br/>Expression(bcb2:(bcb1:(bcb0 + bcb3) - bcb3) + 0) at 15:2-15:2<br/> 15:2-15:2: @4.Return: return</td></tr><tr><td align="left" balign="left">bb4: Return</td></tr></table>>]; + bcb1__Cov_0_3 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">bcb1</td></tr><tr><td align="left" balign="left">Expression(bcb0 + bcb3) at 10:5-11:17<br/> 11:12-11:17: @2.Call: _2 = bar() -> [return: bb3, unwind: bb6]</td></tr><tr><td align="left" balign="left">bb1: FalseUnwind<br/>bb2: Call</td></tr><tr><td align="left" balign="left">bb3: SwitchInt</td></tr></table>>]; + bcb0__Cov_0_3 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">bcb0</td></tr><tr><td align="left" balign="left"></td></tr><tr><td align="left" balign="left">Counter(bcb0) at 9:1-9:11<br/> </td></tr><tr><td align="left" balign="left">bb0: Goto</td></tr></table>>]; + bcb3__Cov_0_3 -> bcb1__Cov_0_3 [label=<>]; + bcb1__Cov_0_3 -> bcb3__Cov_0_3 [label=<false>]; + bcb1__Cov_0_3 -> bcb2__Cov_0_3 [label=<otherwise>]; + bcb0__Cov_0_3 -> bcb1__Cov_0_3 [label=<>]; } diff --git a/src/test/mir-opt/inline/inline_diverging.h.Inline.diff b/src/test/mir-opt/inline/inline_diverging.h.Inline.diff index e2fad5b60eb..f810beeeee3 100644 --- a/src/test/mir-opt/inline/inline_diverging.h.Inline.diff +++ b/src/test/mir-opt/inline/inline_diverging.h.Inline.diff @@ -47,7 +47,7 @@ + _4 = &_2; // scope 1 at $DIR/inline-diverging.rs:22:5: 22:22 + StorageLive(_9); // scope 1 at $DIR/inline-diverging.rs:22:5: 22:22 + _9 = const (); // scope 1 at $DIR/inline-diverging.rs:22:5: 22:22 -+ goto -> bb1; // scope 4 at $DIR/inline-diverging.rs:22:5: 22:22 ++ goto -> bb1; // scope 5 at $DIR/inline-diverging.rs:22:5: 22:22 } bb1: { diff --git a/src/test/mir-opt/instrument_coverage.main.InstrumentCoverage.diff b/src/test/mir-opt/instrument_coverage.main.InstrumentCoverage.diff index 3539fc8b487..34ba7dfdcc5 100644 --- a/src/test/mir-opt/instrument_coverage.main.InstrumentCoverage.diff +++ b/src/test/mir-opt/instrument_coverage.main.InstrumentCoverage.diff @@ -8,38 +8,43 @@ let mut _3: !; // in scope 0 at /the/src/instrument_coverage.rs:12:18: 14:10 bb0: { -+ Coverage::Counter(1) for /the/src/instrument_coverage.rs:10:1 - 12:17; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6 - falseUnwind -> [real: bb1, cleanup: bb5]; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6 ++ Coverage::Counter(1) for /the/src/instrument_coverage.rs:10:1 - 10:11; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6 + goto -> bb1; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6 } bb1: { ++ Coverage::Expression(4294967295) = 1 + 2 for /the/src/instrument_coverage.rs:11:5 - 12:17; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6 + falseUnwind -> [real: bb2, cleanup: bb6]; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6 + } + + bb2: { StorageLive(_2); // scope 0 at /the/src/instrument_coverage.rs:12:12: 12:17 - _2 = bar() -> [return: bb2, unwind: bb5]; // scope 0 at /the/src/instrument_coverage.rs:12:12: 12:17 + _2 = bar() -> [return: bb3, unwind: bb6]; // scope 0 at /the/src/instrument_coverage.rs:12:12: 12:17 // mir::Constant // + span: /the/src/instrument_coverage.rs:12:12: 12:15 // + literal: Const { ty: fn() -> bool {bar}, val: Value(Scalar(<ZST>)) } } - bb2: { - switchInt(move _2) -> [false: bb4, otherwise: bb3]; // scope 0 at /the/src/instrument_coverage.rs:12:12: 12:17 + bb3: { + switchInt(move _2) -> [false: bb5, otherwise: bb4]; // scope 0 at /the/src/instrument_coverage.rs:12:12: 12:17 } - bb3: { -+ Coverage::Expression(4294967294) = 2 + 0 for /the/src/instrument_coverage.rs:16:1 - 16:2; // scope 0 at /the/src/instrument_coverage.rs:16:2: 16:2 -+ Coverage::Counter(2) for /the/src/instrument_coverage.rs:13:13 - 13:18; // scope 0 at /the/src/instrument_coverage.rs:16:2: 16:2 + bb4: { ++ Coverage::Expression(4294967293) = 4294967294 + 0 for /the/src/instrument_coverage.rs:16:1 - 16:2; // scope 0 at /the/src/instrument_coverage.rs:16:2: 16:2 ++ Coverage::Expression(4294967294) = 4294967295 - 2 for /the/src/instrument_coverage.rs:13:13 - 13:18; // scope 0 at /the/src/instrument_coverage.rs:16:2: 16:2 _0 = const (); // scope 0 at /the/src/instrument_coverage.rs:13:13: 13:18 StorageDead(_2); // scope 0 at /the/src/instrument_coverage.rs:14:9: 14:10 return; // scope 0 at /the/src/instrument_coverage.rs:16:2: 16:2 } - bb4: { -+ Coverage::Expression(4294967295) = 1 - 2 for /the/src/instrument_coverage.rs:14:10 - 14:11; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6 + bb5: { ++ Coverage::Counter(2) for /the/src/instrument_coverage.rs:14:10 - 14:11; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6 _1 = const (); // scope 0 at /the/src/instrument_coverage.rs:14:10: 14:10 StorageDead(_2); // scope 0 at /the/src/instrument_coverage.rs:14:9: 14:10 - goto -> bb0; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6 + goto -> bb1; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6 } - bb5 (cleanup): { + bb6 (cleanup): { resume; // scope 0 at /the/src/instrument_coverage.rs:10:1: 16:2 } } diff --git a/src/test/mir-opt/simplify_cfg.main.SimplifyCfg-early-opt.diff b/src/test/mir-opt/simplify_cfg.main.SimplifyCfg-early-opt.diff index eac9328500d..1c5a8900236 100644 --- a/src/test/mir-opt/simplify_cfg.main.SimplifyCfg-early-opt.diff +++ b/src/test/mir-opt/simplify_cfg.main.SimplifyCfg-early-opt.diff @@ -8,40 +8,44 @@ let mut _3: !; // in scope 0 at $DIR/simplify_cfg.rs:9:18: 11:10 bb0: { -- goto -> bb1; // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6 + goto -> bb1; // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6 + } + + bb1: { +- goto -> bb2; // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6 - } - -- bb1: { +- bb2: { StorageLive(_2); // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17 -- _2 = bar() -> [return: bb2, unwind: bb5]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17 -+ _2 = bar() -> [return: bb1, unwind: bb4]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17 +- _2 = bar() -> [return: bb3, unwind: bb6]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17 ++ _2 = bar() -> [return: bb2, unwind: bb5]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17 // mir::Constant // + span: $DIR/simplify_cfg.rs:9:12: 9:15 // + literal: Const { ty: fn() -> bool {bar}, val: Value(Scalar(<ZST>)) } } -- bb2: { -- switchInt(move _2) -> [false: bb4, otherwise: bb3]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17 -+ bb1: { -+ switchInt(move _2) -> [false: bb3, otherwise: bb2]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17 - } - - bb3: { +- switchInt(move _2) -> [false: bb5, otherwise: bb4]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17 + bb2: { ++ switchInt(move _2) -> [false: bb4, otherwise: bb3]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17 + } + +- bb4: { ++ bb3: { _0 = const (); // scope 0 at $DIR/simplify_cfg.rs:10:13: 10:18 StorageDead(_2); // scope 0 at $DIR/simplify_cfg.rs:11:9: 11:10 return; // scope 0 at $DIR/simplify_cfg.rs:13:2: 13:2 } -- bb4: { -+ bb3: { +- bb5: { ++ bb4: { _1 = const (); // scope 0 at $DIR/simplify_cfg.rs:11:10: 11:10 StorageDead(_2); // scope 0 at $DIR/simplify_cfg.rs:11:9: 11:10 - goto -> bb0; // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6 + goto -> bb1; // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6 } -- bb5 (cleanup): { -+ bb4 (cleanup): { +- bb6 (cleanup): { ++ bb5 (cleanup): { resume; // scope 0 at $DIR/simplify_cfg.rs:7:1: 13:2 } } diff --git a/src/test/mir-opt/simplify_cfg.main.SimplifyCfg-initial.diff b/src/test/mir-opt/simplify_cfg.main.SimplifyCfg-initial.diff index f5ac2a41f5f..b079bd7b57c 100644 --- a/src/test/mir-opt/simplify_cfg.main.SimplifyCfg-initial.diff +++ b/src/test/mir-opt/simplify_cfg.main.SimplifyCfg-initial.diff @@ -8,38 +8,35 @@ let mut _3: !; // in scope 0 at $DIR/simplify_cfg.rs:9:18: 11:10 bb0: { -- goto -> bb1; // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6 -+ falseUnwind -> [real: bb1, cleanup: bb5]; // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6 + goto -> bb1; // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6 } bb1: { - falseUnwind -> [real: bb2, cleanup: bb11]; // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6 -- } -- -- bb2: { ++ falseUnwind -> [real: bb2, cleanup: bb6]; // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6 + } + + bb2: { StorageLive(_2); // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17 - _2 = bar() -> [return: bb3, unwind: bb11]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17 -+ _2 = bar() -> [return: bb2, unwind: bb5]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17 ++ _2 = bar() -> [return: bb3, unwind: bb6]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17 // mir::Constant // + span: $DIR/simplify_cfg.rs:9:12: 9:15 // + literal: Const { ty: fn() -> bool {bar}, val: Value(Scalar(<ZST>)) } } -- bb3: { -- switchInt(move _2) -> [false: bb5, otherwise: bb4]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17 -+ bb2: { -+ switchInt(move _2) -> [false: bb4, otherwise: bb3]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17 + bb3: { + switchInt(move _2) -> [false: bb5, otherwise: bb4]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17 } -- bb4: { -+ bb3: { + bb4: { _0 = const (); // scope 0 at $DIR/simplify_cfg.rs:10:13: 10:18 - goto -> bb10; // scope 0 at $DIR/simplify_cfg.rs:10:13: 10:18 + StorageDead(_2); // scope 0 at $DIR/simplify_cfg.rs:11:9: 11:10 + return; // scope 0 at $DIR/simplify_cfg.rs:13:2: 13:2 } -- bb5: { + bb5: { - goto -> bb8; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17 - } - @@ -52,15 +49,13 @@ - } - - bb8: { -+ bb4: { _1 = const (); // scope 0 at $DIR/simplify_cfg.rs:11:10: 11:10 - goto -> bb9; // scope 0 at $DIR/simplify_cfg.rs:9:9: 11:10 - } - - bb9: { StorageDead(_2); // scope 0 at $DIR/simplify_cfg.rs:11:9: 11:10 -- goto -> bb1; // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6 -+ goto -> bb0; // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6 + goto -> bb1; // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6 } - bb10: { @@ -69,7 +64,7 @@ - } - - bb11 (cleanup): { -+ bb5 (cleanup): { ++ bb6 (cleanup): { resume; // scope 0 at $DIR/simplify_cfg.rs:7:1: 13:2 } } diff --git a/src/test/mir-opt/while_storage.while_loop.PreCodegen.after.mir b/src/test/mir-opt/while_storage.while_loop.PreCodegen.after.mir index 9db77d705ff..ec2d161251b 100644 --- a/src/test/mir-opt/while_storage.while_loop.PreCodegen.after.mir +++ b/src/test/mir-opt/while_storage.while_loop.PreCodegen.after.mir @@ -9,51 +9,55 @@ fn while_loop(_1: bool) -> () { let mut _5: bool; // in scope 0 at $DIR/while-storage.rs:11:21: 11:22 bb0: { + goto -> bb1; // scope 0 at $DIR/while-storage.rs:10:5: 14:6 + } + + bb1: { StorageLive(_2); // scope 0 at $DIR/while-storage.rs:10:11: 10:22 StorageLive(_3); // scope 0 at $DIR/while-storage.rs:10:20: 10:21 _3 = _1; // scope 0 at $DIR/while-storage.rs:10:20: 10:21 - _2 = get_bool(move _3) -> bb1; // scope 0 at $DIR/while-storage.rs:10:11: 10:22 + _2 = get_bool(move _3) -> bb2; // scope 0 at $DIR/while-storage.rs:10:11: 10:22 // mir::Constant // + span: $DIR/while-storage.rs:10:11: 10:19 // + literal: Const { ty: fn(bool) -> bool {get_bool}, val: Value(Scalar(<ZST>)) } } - bb1: { + bb2: { StorageDead(_3); // scope 0 at $DIR/while-storage.rs:10:21: 10:22 - switchInt(move _2) -> [false: bb6, otherwise: bb2]; // scope 0 at $DIR/while-storage.rs:10:11: 10:22 + switchInt(move _2) -> [false: bb7, otherwise: bb3]; // scope 0 at $DIR/while-storage.rs:10:11: 10:22 } - bb2: { + bb3: { StorageLive(_4); // scope 0 at $DIR/while-storage.rs:11:12: 11:23 StorageLive(_5); // scope 0 at $DIR/while-storage.rs:11:21: 11:22 _5 = _1; // scope 0 at $DIR/while-storage.rs:11:21: 11:22 - _4 = get_bool(move _5) -> bb3; // scope 0 at $DIR/while-storage.rs:11:12: 11:23 + _4 = get_bool(move _5) -> bb4; // scope 0 at $DIR/while-storage.rs:11:12: 11:23 // mir::Constant // + span: $DIR/while-storage.rs:11:12: 11:20 // + literal: Const { ty: fn(bool) -> bool {get_bool}, val: Value(Scalar(<ZST>)) } } - bb3: { + bb4: { StorageDead(_5); // scope 0 at $DIR/while-storage.rs:11:22: 11:23 - switchInt(move _4) -> [false: bb5, otherwise: bb4]; // scope 0 at $DIR/while-storage.rs:11:12: 11:23 + switchInt(move _4) -> [false: bb6, otherwise: bb5]; // scope 0 at $DIR/while-storage.rs:11:12: 11:23 } - bb4: { + bb5: { StorageDead(_4); // scope 0 at $DIR/while-storage.rs:13:9: 13:10 - goto -> bb7; // scope 0 at no-location + goto -> bb8; // scope 0 at no-location } - bb5: { + bb6: { StorageDead(_4); // scope 0 at $DIR/while-storage.rs:13:9: 13:10 StorageDead(_2); // scope 0 at $DIR/while-storage.rs:14:5: 14:6 - goto -> bb0; // scope 0 at $DIR/while-storage.rs:10:5: 14:6 + goto -> bb1; // scope 0 at $DIR/while-storage.rs:10:5: 14:6 } - bb6: { - goto -> bb7; // scope 0 at no-location + bb7: { + goto -> bb8; // scope 0 at no-location } - bb7: { + bb8: { StorageDead(_2); // scope 0 at $DIR/while-storage.rs:14:5: 14:6 return; // scope 0 at $DIR/while-storage.rs:15:2: 15:2 } diff --git a/src/test/ui/async-await/issue-76547.nll.stderr b/src/test/ui/async-await/issue-76547.nll.stderr index 2456d6a1474..0ac2a396669 100644 --- a/src/test/ui/async-await/issue-76547.nll.stderr +++ b/src/test/ui/async-await/issue-76547.nll.stderr @@ -1,20 +1,22 @@ error: lifetime may not live long enough - --> $DIR/issue-76547.rs:19:14 + --> $DIR/issue-76547.rs:20:13 | LL | async fn fut(bufs: &mut [&mut [u8]]) { - | ^^^^ - - let's call the lifetime of this reference `'2` - | | | - | | let's call the lifetime of this reference `'1` - | assignment requires that `'1` must outlive `'2` + | - - let's call the lifetime of this reference `'2` + | | + | let's call the lifetime of this reference `'1` +LL | ListFut(bufs).await + | ^^^^ this usage requires that `'1` must outlive `'2` error: lifetime may not live long enough - --> $DIR/issue-76547.rs:33:15 + --> $DIR/issue-76547.rs:34:14 | LL | async fn fut2(bufs: &mut [&mut [u8]]) -> i32 { - | ^^^^ - - let's call the lifetime of this reference `'2` - | | | - | | let's call the lifetime of this reference `'1` - | assignment requires that `'1` must outlive `'2` + | - - let's call the lifetime of this reference `'2` + | | + | let's call the lifetime of this reference `'1` +LL | ListFut2(bufs).await + | ^^^^ this usage requires that `'1` must outlive `'2` error: aborting due to 2 previous errors diff --git a/src/test/ui/borrowck/borrowck-in-static.stderr b/src/test/ui/borrowck/borrowck-in-static.stderr index f73c787346d..30e74c5ec95 100644 --- a/src/test/ui/borrowck/borrowck-in-static.stderr +++ b/src/test/ui/borrowck/borrowck-in-static.stderr @@ -4,7 +4,10 @@ error[E0507]: cannot move out of `x`, a captured variable in an `Fn` closure LL | let x = Box::new(0); | - captured outer variable LL | Box::new(|| x) - | ^ move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait + | ---^ + | | | + | | move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait + | captured by this `Fn` closure error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-move-by-capture.stderr b/src/test/ui/borrowck/borrowck-move-by-capture.stderr index 628f206e0a8..05489cf18e7 100644 --- a/src/test/ui/borrowck/borrowck-move-by-capture.stderr +++ b/src/test/ui/borrowck/borrowck-move-by-capture.stderr @@ -1,15 +1,18 @@ error[E0507]: cannot move out of `bar`, a captured variable in an `FnMut` closure --> $DIR/borrowck-move-by-capture.rs:9:29 | -LL | let bar: Box<_> = box 3; - | --- captured outer variable -LL | let _g = to_fn_mut(|| { -LL | let _h = to_fn_once(move || -> isize { *bar }); - | ^^^^^^^^^^^^^^^^ ---- - | | | - | | move occurs because `bar` has type `Box<isize>`, which does not implement the `Copy` trait - | | move occurs due to use in closure - | move out of `bar` occurs here +LL | let bar: Box<_> = box 3; + | --- captured outer variable +LL | let _g = to_fn_mut(|| { + | ________________________- +LL | | let _h = to_fn_once(move || -> isize { *bar }); + | | ^^^^^^^^^^^^^^^^ ---- + | | | | + | | | move occurs because `bar` has type `Box<isize>`, which does not implement the `Copy` trait + | | | move occurs due to use in closure + | | move out of `bar` occurs here +LL | | }); + | |_____- captured by this `FnMut` closure error: aborting due to previous error diff --git a/src/test/ui/borrowck/issue-87456-point-to-closure.rs b/src/test/ui/borrowck/issue-87456-point-to-closure.rs new file mode 100644 index 00000000000..9fc12ba7490 --- /dev/null +++ b/src/test/ui/borrowck/issue-87456-point-to-closure.rs @@ -0,0 +1,14 @@ +// Regression test for #87456. + +fn take_mut(_val: impl FnMut()) {} + +fn main() { + let val = String::new(); + //~^ NOTE: captured outer variable + take_mut(|| { + //~^ NOTE: captured by this `FnMut` closure + let _foo: String = val; + //~^ ERROR: cannot move out of `val`, a captured variable in an `FnMut` closure [E0507] + //~| NOTE: move occurs because + }) +} diff --git a/src/test/ui/borrowck/issue-87456-point-to-closure.stderr b/src/test/ui/borrowck/issue-87456-point-to-closure.stderr new file mode 100644 index 00000000000..fd38ad7bb0a --- /dev/null +++ b/src/test/ui/borrowck/issue-87456-point-to-closure.stderr @@ -0,0 +1,22 @@ +error[E0507]: cannot move out of `val`, a captured variable in an `FnMut` closure + --> $DIR/issue-87456-point-to-closure.rs:10:28 + | +LL | let val = String::new(); + | --- captured outer variable +LL | +LL | take_mut(|| { + | ______________- +LL | | +LL | | let _foo: String = val; + | | ^^^ + | | | + | | move occurs because `val` has type `String`, which does not implement the `Copy` trait + | | help: consider borrowing here: `&val` +LL | | +LL | | +LL | | }) + | |_____- captured by this `FnMut` closure + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`. diff --git a/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr b/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr index dbba33f0183..1663ce81d6c 100644 --- a/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr +++ b/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr @@ -1,11 +1,15 @@ error[E0507]: cannot move out of `y`, a captured variable in an `Fn` closure --> $DIR/unboxed-closures-move-upvar-from-non-once-ref-closure.rs:11:9 | -LL | let y = vec![format!("World")]; - | - captured outer variable -LL | call(|| { -LL | y.into_iter(); - | ^ move occurs because `y` has type `Vec<String>`, which does not implement the `Copy` trait +LL | let y = vec![format!("World")]; + | - captured outer variable +LL | call(|| { + | __________- +LL | | y.into_iter(); + | | ^ move occurs because `y` has type `Vec<String>`, which does not implement the `Copy` trait +LL | | +LL | | }); + | |_____- captured by this `Fn` closure error: aborting due to previous error diff --git a/src/test/ui/const-generics/issues/issue-87493.rs b/src/test/ui/const-generics/issues/issue-87493.rs new file mode 100644 index 00000000000..d8599ab22a3 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-87493.rs @@ -0,0 +1,14 @@ +pub trait MyTrait { + type Assoc; +} + +pub fn foo<S, T>(_s: S, _t: T) +where + S: MyTrait, + T: MyTrait<Assoc == S::Assoc>, + //~^ ERROR: expected one of `,` or `>`, found `==` + //~| ERROR: this trait takes 0 generic arguments but 1 generic argument was supplied +{ +} + +fn main() {} diff --git a/src/test/ui/const-generics/issues/issue-87493.stderr b/src/test/ui/const-generics/issues/issue-87493.stderr new file mode 100644 index 00000000000..8f92eeaffd1 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-87493.stderr @@ -0,0 +1,28 @@ +error: expected one of `,` or `>`, found `==` + --> $DIR/issue-87493.rs:8:22 + | +LL | T: MyTrait<Assoc == S::Assoc>, + | ^^ expected one of `,` or `>` + | +help: if you meant to use an associated type binding, replace `==` with `=` + | +LL | T: MyTrait<Assoc = S::Assoc>, + | ~ + +error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/issue-87493.rs:8:8 + | +LL | T: MyTrait<Assoc == S::Assoc>, + | ^^^^^^^------------------- help: remove these generics + | | + | expected 0 generic arguments + | +note: trait defined here, with 0 generic parameters + --> $DIR/issue-87493.rs:1:11 + | +LL | pub trait MyTrait { + | ^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0107`. diff --git a/src/test/ui/consts/const-eval/const_panic.rs b/src/test/ui/consts/const-eval/const_panic.rs index e4455d86a14..100faded079 100644 --- a/src/test/ui/consts/const-eval/const_panic.rs +++ b/src/test/ui/consts/const-eval/const_panic.rs @@ -15,10 +15,13 @@ const Y: () = std::unreachable!(); const X: () = std::unimplemented!(); //~^ ERROR evaluation of constant value failed -// + const W: () = std::panic!(MSG); //~^ ERROR evaluation of constant value failed +const W2: () = std::panic!("{}", MSG); +//~^ ERROR evaluation of constant value failed + const Z_CORE: () = core::panic!("cheese"); //~^ ERROR evaluation of constant value failed @@ -33,3 +36,6 @@ const X_CORE: () = core::unimplemented!(); const W_CORE: () = core::panic!(MSG); //~^ ERROR evaluation of constant value failed + +const W2_CORE: () = core::panic!("{}", MSG); +//~^ ERROR evaluation of constant value failed diff --git a/src/test/ui/consts/const-eval/const_panic.stderr b/src/test/ui/consts/const-eval/const_panic.stderr index c0c749ede56..e98e4a506c0 100644 --- a/src/test/ui/consts/const-eval/const_panic.stderr +++ b/src/test/ui/consts/const-eval/const_panic.stderr @@ -39,45 +39,61 @@ LL | const W: () = std::panic!(MSG); = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: evaluation of constant value failed - --> $DIR/const_panic.rs:22:20 + --> $DIR/const_panic.rs:22:16 + | +LL | const W2: () = std::panic!("{}", MSG); + | ^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'hello', $DIR/const_panic.rs:22:16 + | + = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0080]: evaluation of constant value failed + --> $DIR/const_panic.rs:25:20 | LL | const Z_CORE: () = core::panic!("cheese"); - | ^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'cheese', $DIR/const_panic.rs:22:20 + | ^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'cheese', $DIR/const_panic.rs:25:20 | = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: evaluation of constant value failed - --> $DIR/const_panic.rs:25:21 + --> $DIR/const_panic.rs:28:21 | LL | const Z2_CORE: () = core::panic!(); - | ^^^^^^^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/const_panic.rs:25:21 + | ^^^^^^^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/const_panic.rs:28:21 | = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: evaluation of constant value failed - --> $DIR/const_panic.rs:28:20 + --> $DIR/const_panic.rs:31:20 | LL | const Y_CORE: () = core::unreachable!(); - | ^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic.rs:28:20 + | ^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic.rs:31:20 | = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: evaluation of constant value failed - --> $DIR/const_panic.rs:31:20 + --> $DIR/const_panic.rs:34:20 | LL | const X_CORE: () = core::unimplemented!(); - | ^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'not implemented', $DIR/const_panic.rs:31:20 + | ^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'not implemented', $DIR/const_panic.rs:34:20 | = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: evaluation of constant value failed - --> $DIR/const_panic.rs:34:20 + --> $DIR/const_panic.rs:37:20 | LL | const W_CORE: () = core::panic!(MSG); - | ^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'hello', $DIR/const_panic.rs:34:20 + | ^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'hello', $DIR/const_panic.rs:37:20 + | + = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0080]: evaluation of constant value failed + --> $DIR/const_panic.rs:40:21 + | +LL | const W2_CORE: () = core::panic!("{}", MSG); + | ^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'hello', $DIR/const_panic.rs:40:21 | = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 10 previous errors +error: aborting due to 12 previous errors For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const-eval/const_panic_2021.rs b/src/test/ui/consts/const-eval/const_panic_2021.rs index daef34cd6a3..9b8652a776e 100644 --- a/src/test/ui/consts/const-eval/const_panic_2021.rs +++ b/src/test/ui/consts/const-eval/const_panic_2021.rs @@ -2,6 +2,8 @@ #![feature(const_panic)] #![crate_type = "lib"] +const MSG: &str = "hello"; + const A: () = std::panic!("blÃ¥haj"); //~^ ERROR evaluation of constant value failed @@ -14,14 +16,20 @@ const C: () = std::unreachable!(); const D: () = std::unimplemented!(); //~^ ERROR evaluation of constant value failed -const E: () = core::panic!("shark"); +const E: () = std::panic!("{}", MSG); +//~^ ERROR evaluation of constant value failed + +const A_CORE: () = core::panic!("shark"); +//~^ ERROR evaluation of constant value failed + +const B_CORE: () = core::panic!(); //~^ ERROR evaluation of constant value failed -const F: () = core::panic!(); +const C_CORE: () = core::unreachable!(); //~^ ERROR evaluation of constant value failed -const G: () = core::unreachable!(); +const D_CORE: () = core::unimplemented!(); //~^ ERROR evaluation of constant value failed -const H: () = core::unimplemented!(); +const E_CORE: () = core::panic!("{}", MSG); //~^ ERROR evaluation of constant value failed diff --git a/src/test/ui/consts/const-eval/const_panic_2021.stderr b/src/test/ui/consts/const-eval/const_panic_2021.stderr index c1bdab3693d..9eb241ae8e5 100644 --- a/src/test/ui/consts/const-eval/const_panic_2021.stderr +++ b/src/test/ui/consts/const-eval/const_panic_2021.stderr @@ -1,67 +1,83 @@ error[E0080]: evaluation of constant value failed - --> $DIR/const_panic_2021.rs:5:15 + --> $DIR/const_panic_2021.rs:7:15 | LL | const A: () = std::panic!("blÃ¥haj"); - | ^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'blÃ¥haj', $DIR/const_panic_2021.rs:5:15 + | ^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'blÃ¥haj', $DIR/const_panic_2021.rs:7:15 | = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: evaluation of constant value failed - --> $DIR/const_panic_2021.rs:8:15 + --> $DIR/const_panic_2021.rs:10:15 | LL | const B: () = std::panic!(); - | ^^^^^^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/const_panic_2021.rs:8:15 + | ^^^^^^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/const_panic_2021.rs:10:15 | = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: evaluation of constant value failed - --> $DIR/const_panic_2021.rs:11:15 + --> $DIR/const_panic_2021.rs:13:15 | LL | const C: () = std::unreachable!(); - | ^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic_2021.rs:11:15 + | ^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic_2021.rs:13:15 | = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: evaluation of constant value failed - --> $DIR/const_panic_2021.rs:14:15 + --> $DIR/const_panic_2021.rs:16:15 | LL | const D: () = std::unimplemented!(); - | ^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'not implemented', $DIR/const_panic_2021.rs:14:15 + | ^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'not implemented', $DIR/const_panic_2021.rs:16:15 | = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: evaluation of constant value failed - --> $DIR/const_panic_2021.rs:17:15 + --> $DIR/const_panic_2021.rs:19:15 | -LL | const E: () = core::panic!("shark"); - | ^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'shark', $DIR/const_panic_2021.rs:17:15 +LL | const E: () = std::panic!("{}", MSG); + | ^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'hello', $DIR/const_panic_2021.rs:19:15 | = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: evaluation of constant value failed - --> $DIR/const_panic_2021.rs:20:15 + --> $DIR/const_panic_2021.rs:22:20 | -LL | const F: () = core::panic!(); - | ^^^^^^^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/const_panic_2021.rs:20:15 +LL | const A_CORE: () = core::panic!("shark"); + | ^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'shark', $DIR/const_panic_2021.rs:22:20 | = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: evaluation of constant value failed - --> $DIR/const_panic_2021.rs:23:15 + --> $DIR/const_panic_2021.rs:25:20 | -LL | const G: () = core::unreachable!(); - | ^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic_2021.rs:23:15 +LL | const B_CORE: () = core::panic!(); + | ^^^^^^^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/const_panic_2021.rs:25:20 + | + = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0080]: evaluation of constant value failed + --> $DIR/const_panic_2021.rs:28:20 + | +LL | const C_CORE: () = core::unreachable!(); + | ^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic_2021.rs:28:20 | = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: evaluation of constant value failed - --> $DIR/const_panic_2021.rs:26:15 + --> $DIR/const_panic_2021.rs:31:20 | -LL | const H: () = core::unimplemented!(); - | ^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'not implemented', $DIR/const_panic_2021.rs:26:15 +LL | const D_CORE: () = core::unimplemented!(); + | ^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'not implemented', $DIR/const_panic_2021.rs:31:20 | = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 8 previous errors +error[E0080]: evaluation of constant value failed + --> $DIR/const_panic_2021.rs:34:20 + | +LL | const E_CORE: () = core::panic!("{}", MSG); + | ^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'hello', $DIR/const_panic_2021.rs:34:20 + | + = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 10 previous errors For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const_fn_trait_bound.rs b/src/test/ui/consts/const_fn_trait_bound.rs index b1ef820d827..19c08b62144 100644 --- a/src/test/ui/consts/const_fn_trait_bound.rs +++ b/src/test/ui/consts/const_fn_trait_bound.rs @@ -8,9 +8,9 @@ const fn test1<T: std::ops::Add>() {} //[stock]~^ trait bounds const fn test2(_x: &dyn Send) {} -//[stock]~^ trait bounds +//[stock]~^ trait objects in const fn are unstable const fn test3() -> &'static dyn Send { loop {} } -//[stock]~^ trait bounds +//[stock]~^ trait objects in const fn are unstable #[rustc_error] diff --git a/src/test/ui/consts/const_fn_trait_bound.stock.stderr b/src/test/ui/consts/const_fn_trait_bound.stock.stderr index 2ad45f3afde..d652b5268a8 100644 --- a/src/test/ui/consts/const_fn_trait_bound.stock.stderr +++ b/src/test/ui/consts/const_fn_trait_bound.stock.stderr @@ -7,7 +7,7 @@ LL | const fn test1<T: std::ops::Add>() {} = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable -error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable +error[E0658]: trait objects in const fn are unstable --> $DIR/const_fn_trait_bound.rs:10:16 | LL | const fn test2(_x: &dyn Send) {} @@ -16,7 +16,7 @@ LL | const fn test2(_x: &dyn Send) {} = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable -error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable +error[E0658]: trait objects in const fn are unstable --> $DIR/const_fn_trait_bound.rs:12:21 | LL | const fn test3() -> &'static dyn Send { loop {} } diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.rs b/src/test/ui/consts/min_const_fn/min_const_fn.rs index bb525d57197..10347a02074 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn.rs +++ b/src/test/ui/consts/min_const_fn/min_const_fn.rs @@ -130,16 +130,16 @@ const fn no_apit(_x: impl std::fmt::Debug) {} //~^ ERROR trait bounds other than `Sized` //~| ERROR destructor const fn no_dyn_trait(_x: &dyn std::fmt::Debug) {} -//~^ ERROR trait bounds other than `Sized` +//~^ ERROR trait objects in const fn are unstable const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() } -//~^ ERROR trait bounds other than `Sized` +//~^ ERROR trait objects in const fn are unstable const fn no_unsafe() { unsafe {} } const fn really_no_traits_i_mean_it() { (&() as &dyn std::fmt::Debug, ()).1 } -//~^ ERROR trait bounds other than `Sized` -//~| ERROR trait bounds other than `Sized` -//~| ERROR trait bounds other than `Sized` +//~^ ERROR trait objects in const fn are unstable +//~| ERROR trait objects in const fn are unstable +//~| ERROR trait objects in const fn are unstable const fn no_fn_ptrs(_x: fn()) {} //~^ ERROR function pointer diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.stderr b/src/test/ui/consts/min_const_fn/min_const_fn.stderr index d1c2a04d6a6..1e275d77bac 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn.stderr +++ b/src/test/ui/consts/min_const_fn/min_const_fn.stderr @@ -279,7 +279,7 @@ LL | const fn no_apit(_x: impl std::fmt::Debug) {} | | | constant functions cannot evaluate destructors -error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable +error[E0658]: trait objects in const fn are unstable --> $DIR/min_const_fn.rs:132:23 | LL | const fn no_dyn_trait(_x: &dyn std::fmt::Debug) {} @@ -288,7 +288,7 @@ LL | const fn no_dyn_trait(_x: &dyn std::fmt::Debug) {} = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable -error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable +error[E0658]: trait objects in const fn are unstable --> $DIR/min_const_fn.rs:134:32 | LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() } @@ -297,7 +297,7 @@ LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() } = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable -error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable +error[E0658]: trait objects in const fn are unstable --> $DIR/min_const_fn.rs:139:41 | LL | const fn really_no_traits_i_mean_it() { (&() as &dyn std::fmt::Debug, ()).1 } @@ -308,7 +308,7 @@ LL | const fn really_no_traits_i_mean_it() { (&() as &dyn std::fmt::Debug, ()).1 = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable -error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable +error[E0658]: trait objects in const fn are unstable --> $DIR/min_const_fn.rs:139:42 | LL | const fn really_no_traits_i_mean_it() { (&() as &dyn std::fmt::Debug, ()).1 } @@ -319,7 +319,7 @@ LL | const fn really_no_traits_i_mean_it() { (&() as &dyn std::fmt::Debug, ()).1 = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable -error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable +error[E0658]: trait objects in const fn are unstable --> $DIR/min_const_fn.rs:139:42 | LL | const fn really_no_traits_i_mean_it() { (&() as &dyn std::fmt::Debug, ()).1 } diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_dyn.rs b/src/test/ui/consts/min_const_fn/min_const_fn_dyn.rs index 6ca1e59b3af..1ab8253b414 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn_dyn.rs +++ b/src/test/ui/consts/min_const_fn/min_const_fn_dyn.rs @@ -7,9 +7,9 @@ struct Hide(HasDyn); const fn no_inner_dyn_trait(_x: Hide) {} const fn no_inner_dyn_trait2(x: Hide) { x.0.field; -//~^ ERROR trait bounds other than `Sized` +//~^ ERROR trait objects in const fn are unstable } const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasDyn { field: &0 }) } -//~^ ERROR trait bounds other than `Sized` +//~^ ERROR trait objects in const fn are unstable fn main() {} diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr index 2cad8a862be..6eec1df5aec 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr +++ b/src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr @@ -1,4 +1,4 @@ -error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable +error[E0658]: trait objects in const fn are unstable --> $DIR/min_const_fn_dyn.rs:9:5 | LL | const fn no_inner_dyn_trait2(x: Hide) { @@ -9,7 +9,7 @@ LL | x.0.field; = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable -error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable +error[E0658]: trait objects in const fn are unstable --> $DIR/min_const_fn_dyn.rs:12:66 | LL | const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasDyn { field: &0 }) } diff --git a/src/test/ui/error-codes/E0439.rs b/src/test/ui/error-codes/E0439.rs deleted file mode 100644 index 86e9cb55a9c..00000000000 --- a/src/test/ui/error-codes/E0439.rs +++ /dev/null @@ -1,8 +0,0 @@ -#![feature(platform_intrinsics)] - -extern "platform-intrinsic" { - fn simd_shuffle<A,B>(a: A, b: A, c: [u32; 8]) -> B; //~ ERROR E0439 -} - -fn main () { -} diff --git a/src/test/ui/error-codes/E0439.stderr b/src/test/ui/error-codes/E0439.stderr deleted file mode 100644 index 8021f7d3951..00000000000 --- a/src/test/ui/error-codes/E0439.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0439]: invalid `simd_shuffle`, needs length: `simd_shuffle` - --> $DIR/E0439.rs:4:5 - | -LL | fn simd_shuffle<A,B>(a: A, b: A, c: [u32; 8]) -> B; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0439`. diff --git a/src/test/ui/issues/issue-4335.stderr b/src/test/ui/issues/issue-4335.stderr index f187969ff4e..fa3b58e1279 100644 --- a/src/test/ui/issues/issue-4335.stderr +++ b/src/test/ui/issues/issue-4335.stderr @@ -4,7 +4,10 @@ error[E0507]: cannot move out of `*v`, as `v` is a captured variable in an `FnMu LL | fn f<'r, T>(v: &'r T) -> Box<dyn FnMut() -> T + 'r> { | - captured outer variable LL | id(Box::new(|| *v)) - | ^^ move occurs because `*v` has type `T`, which does not implement the `Copy` trait + | ---^^ + | | | + | | move occurs because `*v` has type `T`, which does not implement the `Copy` trait + | captured by this `FnMut` closure error: aborting due to previous error diff --git a/src/test/ui/issues/issue-51102.stderr b/src/test/ui/issues/issue-51102.stderr index eb9eb680200..09c52292dcc 100644 --- a/src/test/ui/issues/issue-51102.stderr +++ b/src/test/ui/issues/issue-51102.stderr @@ -2,7 +2,10 @@ error[E0026]: struct `SimpleStruct` does not have a field named `state` --> $DIR/issue-51102.rs:13:17 | LL | state: 0, - | ^^^^^ struct `SimpleStruct` does not have this field + | ^^^^^ + | | + | struct `SimpleStruct` does not have this field + | help: `SimpleStruct` has a field named `no_state_here` error[E0025]: field `no_state_here` bound multiple times in the pattern --> $DIR/issue-51102.rs:24:17 diff --git a/src/test/ui/issues/issue-55796.stderr b/src/test/ui/issues/issue-55796.stderr index ffe3bb737ad..952159ffc3b 100644 --- a/src/test/ui/issues/issue-55796.stderr +++ b/src/test/ui/issues/issue-55796.stderr @@ -15,7 +15,7 @@ note: ...so that the type `Map<<Self as Graph<'a>>::EdgesIter, [closure@$DIR/iss LL | Box::new(self.out_edges(u).map(|e| e.target())) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: but, the lifetime must be valid for the static lifetime... -note: ...so that the expression is assignable +note: ...so that the types are compatible --> $DIR/issue-55796.rs:18:9 | LL | Box::new(self.out_edges(u).map(|e| e.target())) @@ -40,7 +40,7 @@ note: ...so that the type `Map<<Self as Graph<'a>>::EdgesIter, [closure@$DIR/iss LL | Box::new(self.in_edges(u).map(|e| e.target())) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: but, the lifetime must be valid for the static lifetime... -note: ...so that the expression is assignable +note: ...so that the types are compatible --> $DIR/issue-55796.rs:23:9 | LL | Box::new(self.in_edges(u).map(|e| e.target())) diff --git a/src/test/ui/issues/issue-61882-2.stderr b/src/test/ui/issues/issue-61882-2.stderr index 03a65540ced..0b8e134c966 100644 --- a/src/test/ui/issues/issue-61882-2.stderr +++ b/src/test/ui/issues/issue-61882-2.stderr @@ -5,7 +5,7 @@ LL | Self(&x); | ^^ | | | borrowed value does not live long enough - | requires that `x` is borrowed for `'static` + | this usage requires that `x` is borrowed for `'static` LL | LL | } | - `x` dropped here while still borrowed diff --git a/src/test/ui/issues/issue-75777.stderr b/src/test/ui/issues/issue-75777.stderr index 16249a33c2f..25562f6347e 100644 --- a/src/test/ui/issues/issue-75777.stderr +++ b/src/test/ui/issues/issue-75777.stderr @@ -17,7 +17,7 @@ LL | Box::new(move |_| fut) = note: expected `(Pin<Box<dyn Future<Output = A> + Send>>,)` found `(Pin<Box<(dyn Future<Output = A> + Send + 'a)>>,)` = note: but, the lifetime must be valid for the static lifetime... -note: ...so that the expression is assignable +note: ...so that the types are compatible --> $DIR/issue-75777.rs:13:5 | LL | Box::new(move |_| fut) diff --git a/src/test/ui/lifetimes/issue-77175.rs b/src/test/ui/lifetimes/issue-77175.rs new file mode 100644 index 00000000000..2282752b6c1 --- /dev/null +++ b/src/test/ui/lifetimes/issue-77175.rs @@ -0,0 +1,19 @@ +#[deny(single_use_lifetimes)] +// edition:2018 +// check-pass + +// Prior to the fix, the compiler complained that the 'a lifetime was only used +// once. This was obviously wrong since the lifetime is used twice: For the s3 +// parameter and the return type. The issue was caused by the compiler +// desugaring the async function into a generator that uses only a single +// lifetime, which then the validator complained about becauase of the +// single_use_lifetimes constraints. +async fn bar<'a>(s1: String, s2: &'_ str, s3: &'a str) -> &'a str { + s3 +} + +fn foo<'a>(s1: String, s2: &'_ str, s3: &'a str) -> &'a str { + s3 +} + +fn main() {} diff --git a/src/test/ui/lifetimes/undeclared-lifetime-used-in-debug-macro-issue-70152.stderr b/src/test/ui/lifetimes/undeclared-lifetime-used-in-debug-macro-issue-70152.stderr index 8c87f6da8dc..e18d725faef 100644 --- a/src/test/ui/lifetimes/undeclared-lifetime-used-in-debug-macro-issue-70152.stderr +++ b/src/test/ui/lifetimes/undeclared-lifetime-used-in-debug-macro-issue-70152.stderr @@ -9,6 +9,17 @@ LL | a: &'b str, = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes error[E0261]: use of undeclared lifetime name `'b` + --> $DIR/undeclared-lifetime-used-in-debug-macro-issue-70152.rs:3:9 + | +LL | #[derive(Eq, PartialEq)] + | -- lifetime `'b` is missing in item created through this procedural macro +LL | struct Test { +LL | a: &'b str, + | ^^ undeclared lifetime + | + = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes + +error[E0261]: use of undeclared lifetime name `'b` --> $DIR/undeclared-lifetime-used-in-debug-macro-issue-70152.rs:13:13 | LL | fn foo(&'b self) {} @@ -24,17 +35,6 @@ help: consider introducing lifetime `'b` here LL | fn foo<'b>(&'b self) {} | ++++ -error[E0261]: use of undeclared lifetime name `'b` - --> $DIR/undeclared-lifetime-used-in-debug-macro-issue-70152.rs:3:9 - | -LL | #[derive(Eq, PartialEq)] - | -- lifetime `'b` is missing in item created through this procedural macro -LL | struct Test { -LL | a: &'b str, - | ^^ undeclared lifetime - | - = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes - error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0261`. diff --git a/src/test/ui/loops/loops-reject-duplicate-labels-2.rs b/src/test/ui/loops/loops-reject-duplicate-labels-2.rs index 3a860f508ff..68a19a8f6f7 100644 --- a/src/test/ui/loops/loops-reject-duplicate-labels-2.rs +++ b/src/test/ui/loops/loops-reject-duplicate-labels-2.rs @@ -1,7 +1,7 @@ // check-pass +#![feature(label_break_value)] - -// Issue #21633: reject duplicate loop labels in function bodies. +// Issue #21633: reject duplicate loop labels and block labels in function bodies. // // This is testing the generalization (to the whole function body) // discussed here: @@ -26,6 +26,8 @@ pub fn foo() { { 'lt: loop { break; } } { 'lt: while let Some(_) = None::<i32> { break; } } //~^ WARN label name `'lt` shadows a label name that is already in scope + { 'bl: {} } + { 'bl: {} } //~ WARN label name `'bl` shadows a label name that is already in scope } diff --git a/src/test/ui/loops/loops-reject-duplicate-labels-2.stderr b/src/test/ui/loops/loops-reject-duplicate-labels-2.stderr index 6c53d04e107..2c372fcff7a 100644 --- a/src/test/ui/loops/loops-reject-duplicate-labels-2.stderr +++ b/src/test/ui/loops/loops-reject-duplicate-labels-2.stderr @@ -62,5 +62,13 @@ LL | { 'lt: loop { break; } } LL | { 'lt: while let Some(_) = None::<i32> { break; } } | ^^^ label `'lt` already in scope -warning: 8 warnings emitted +warning: label name `'bl` shadows a label name that is already in scope + --> $DIR/loops-reject-duplicate-labels-2.rs:30:7 + | +LL | { 'bl: {} } + | --- first declared here +LL | { 'bl: {} } + | ^^^ label `'bl` already in scope + +warning: 9 warnings emitted diff --git a/src/test/ui/loops/loops-reject-duplicate-labels.rs b/src/test/ui/loops/loops-reject-duplicate-labels.rs index d9334ce3857..c34bcf3df1d 100644 --- a/src/test/ui/loops/loops-reject-duplicate-labels.rs +++ b/src/test/ui/loops/loops-reject-duplicate-labels.rs @@ -1,8 +1,7 @@ // check-pass +#![feature(label_break_value)] - -// Issue #21633: reject duplicate loop labels in function bodies. -// This is testing the exact cases that are in the issue description. +// Issue #21633: reject duplicate loop labels and block labels in function bodies. #[allow(unused_labels)] fn foo() { @@ -24,6 +23,8 @@ fn foo() { 'lt: loop { break; } 'lt: while let Some(_) = None::<i32> { break; } //~^ WARN label name `'lt` shadows a label name that is already in scope + 'bl: {} + 'bl: {} //~ WARN label name `'bl` shadows a label name that is already in scope } // Note however that it is okay for the same label to be reused in @@ -33,6 +34,8 @@ struct S; impl S { fn m1(&self) { 'okay: loop { break 'okay; } } fn m2(&self) { 'okay: loop { break 'okay; } } + fn m3(&self) { 'okay: { break 'okay; } } + fn m4(&self) { 'okay: { break 'okay; } } } @@ -40,5 +43,7 @@ pub fn main() { let s = S; s.m1(); s.m2(); + s.m3(); + s.m4(); foo(); } diff --git a/src/test/ui/loops/loops-reject-duplicate-labels.stderr b/src/test/ui/loops/loops-reject-duplicate-labels.stderr index 5bdf64849f3..3bf3af763ec 100644 --- a/src/test/ui/loops/loops-reject-duplicate-labels.stderr +++ b/src/test/ui/loops/loops-reject-duplicate-labels.stderr @@ -1,5 +1,5 @@ warning: label name `'fl` shadows a label name that is already in scope - --> $DIR/loops-reject-duplicate-labels.rs:10:5 + --> $DIR/loops-reject-duplicate-labels.rs:9:5 | LL | 'fl: for _ in 0..10 { break; } | --- first declared here @@ -7,7 +7,7 @@ LL | 'fl: loop { break; } | ^^^ label `'fl` already in scope warning: label name `'lf` shadows a label name that is already in scope - --> $DIR/loops-reject-duplicate-labels.rs:13:5 + --> $DIR/loops-reject-duplicate-labels.rs:12:5 | LL | 'lf: loop { break; } | --- first declared here @@ -15,7 +15,7 @@ LL | 'lf: for _ in 0..10 { break; } | ^^^ label `'lf` already in scope warning: label name `'wl` shadows a label name that is already in scope - --> $DIR/loops-reject-duplicate-labels.rs:15:5 + --> $DIR/loops-reject-duplicate-labels.rs:14:5 | LL | 'wl: while 2 > 1 { break; } | --- first declared here @@ -23,7 +23,7 @@ LL | 'wl: loop { break; } | ^^^ label `'wl` already in scope warning: label name `'lw` shadows a label name that is already in scope - --> $DIR/loops-reject-duplicate-labels.rs:17:5 + --> $DIR/loops-reject-duplicate-labels.rs:16:5 | LL | 'lw: loop { break; } | --- first declared here @@ -31,7 +31,7 @@ LL | 'lw: while 2 > 1 { break; } | ^^^ label `'lw` already in scope warning: label name `'fw` shadows a label name that is already in scope - --> $DIR/loops-reject-duplicate-labels.rs:19:5 + --> $DIR/loops-reject-duplicate-labels.rs:18:5 | LL | 'fw: for _ in 0..10 { break; } | --- first declared here @@ -39,7 +39,7 @@ LL | 'fw: while 2 > 1 { break; } | ^^^ label `'fw` already in scope warning: label name `'wf` shadows a label name that is already in scope - --> $DIR/loops-reject-duplicate-labels.rs:21:5 + --> $DIR/loops-reject-duplicate-labels.rs:20:5 | LL | 'wf: while 2 > 1 { break; } | --- first declared here @@ -47,7 +47,7 @@ LL | 'wf: for _ in 0..10 { break; } | ^^^ label `'wf` already in scope warning: label name `'tl` shadows a label name that is already in scope - --> $DIR/loops-reject-duplicate-labels.rs:23:5 + --> $DIR/loops-reject-duplicate-labels.rs:22:5 | LL | 'tl: while let Some(_) = None::<i32> { break; } | --- first declared here @@ -55,12 +55,20 @@ LL | 'tl: loop { break; } | ^^^ label `'tl` already in scope warning: label name `'lt` shadows a label name that is already in scope - --> $DIR/loops-reject-duplicate-labels.rs:25:5 + --> $DIR/loops-reject-duplicate-labels.rs:24:5 | LL | 'lt: loop { break; } | --- first declared here LL | 'lt: while let Some(_) = None::<i32> { break; } | ^^^ label `'lt` already in scope -warning: 8 warnings emitted +warning: label name `'bl` shadows a label name that is already in scope + --> $DIR/loops-reject-duplicate-labels.rs:27:5 + | +LL | 'bl: {} + | --- first declared here +LL | 'bl: {} + | ^^^ label `'bl` already in scope + +warning: 9 warnings emitted diff --git a/src/test/ui/loops/loops-reject-lifetime-shadowing-label.rs b/src/test/ui/loops/loops-reject-lifetime-shadowing-label.rs index 3212b78b08c..ce2d07eb06a 100644 --- a/src/test/ui/loops/loops-reject-lifetime-shadowing-label.rs +++ b/src/test/ui/loops/loops-reject-lifetime-shadowing-label.rs @@ -1,10 +1,10 @@ // check-pass - +#![feature(label_break_value)] #![allow(dead_code, unused_variables)] -// Issue #21633: reject duplicate loop labels in function bodies. +// Issue #21633: reject duplicate loop labels and block labels in function bodies. // -// Test rejection of lifetimes in *expressions* that shadow loop labels. +// Test rejection of lifetimes in *expressions* that shadow labels. fn foo() { // Reusing lifetime `'a` in function item is okay. @@ -23,8 +23,13 @@ fn foo() { assert_eq!((*b)(&z), z); break 'a; } -} + 'b: { + let b = Box::new(|x: &()| ()) as Box<dyn for <'b> Fn(&'b ())>; + //~^ WARN lifetime name `'b` shadows a label name that is already in scope + break 'b; + } +} pub fn main() { foo(); diff --git a/src/test/ui/loops/loops-reject-lifetime-shadowing-label.stderr b/src/test/ui/loops/loops-reject-lifetime-shadowing-label.stderr index dcee1a80090..9702b71600b 100644 --- a/src/test/ui/loops/loops-reject-lifetime-shadowing-label.stderr +++ b/src/test/ui/loops/loops-reject-lifetime-shadowing-label.stderr @@ -6,5 +6,13 @@ LL | 'a: loop { LL | let b = Box::new(|x: &i8| *x) as Box<dyn for <'a> Fn(&'a i8) -> i8>; | ^^ label `'a` already in scope -warning: 1 warning emitted +warning: lifetime name `'b` shadows a label name that is already in scope + --> $DIR/loops-reject-lifetime-shadowing-label.rs:28:55 + | +LL | 'b: { + | -- first declared here +LL | let b = Box::new(|x: &()| ()) as Box<dyn for <'b> Fn(&'b ())>; + | ^^ label `'b` already in scope + +warning: 2 warnings emitted diff --git a/src/test/ui/macros/lint-trailing-macro-call.rs b/src/test/ui/macros/lint-trailing-macro-call.rs new file mode 100644 index 00000000000..f8e84756391 --- /dev/null +++ b/src/test/ui/macros/lint-trailing-macro-call.rs @@ -0,0 +1,16 @@ +// check-pass +// +// Ensures that we properly lint +// a removed 'expression' resulting from a macro +// in trailing expression position + +macro_rules! expand_it { + () => { + #[cfg(FALSE)] 25; //~ WARN trailing semicolon in macro + //~| WARN this was previously + } +} + +fn main() { + expand_it!() +} diff --git a/src/test/ui/macros/lint-trailing-macro-call.stderr b/src/test/ui/macros/lint-trailing-macro-call.stderr new file mode 100644 index 00000000000..a98a559c8af --- /dev/null +++ b/src/test/ui/macros/lint-trailing-macro-call.stderr @@ -0,0 +1,18 @@ +warning: trailing semicolon in macro used in expression position + --> $DIR/lint-trailing-macro-call.rs:9:25 + | +LL | #[cfg(FALSE)] 25; + | ^ +... +LL | expand_it!() + | ------------ in this macro invocation + | + = note: `#[warn(semicolon_in_expressions_from_macros)]` on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #79813 <https://github.com/rust-lang/rust/issues/79813> + = note: macro invocations at the end of a block are treated as expressions + = note: to ignore the value produced by the macro, add a semicolon after the invocation of `expand_it` + = note: this warning originates in the macro `expand_it` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: 1 warning emitted + diff --git a/src/test/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.stderr b/src/test/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.stderr index 9427ba546a9..e12af2d4527 100644 --- a/src/test/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.stderr +++ b/src/test/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.stderr @@ -4,7 +4,10 @@ error[E0507]: cannot move out of `i`, a captured variable in an `Fn` closure LL | let i = box 3; | - captured outer variable LL | let _f = to_fn(|| test(i)); - | ^ move occurs because `i` has type `Box<usize>`, which does not implement the `Copy` trait + | --------^- + | | | + | | move occurs because `i` has type `Box<usize>`, which does not implement the `Copy` trait + | captured by this `Fn` closure error: aborting due to previous error diff --git a/src/test/ui/nll/issue-46036.stderr b/src/test/ui/nll/issue-46036.stderr index 49dd0e267b8..e6e95ee6136 100644 --- a/src/test/ui/nll/issue-46036.stderr +++ b/src/test/ui/nll/issue-46036.stderr @@ -5,7 +5,7 @@ LL | let foo = Foo { x: &a }; | ^^ | | | borrowed value does not live long enough - | requires that `a` is borrowed for `'static` + | this usage requires that `a` is borrowed for `'static` LL | loop { } LL | } | - `a` dropped here while still borrowed diff --git a/src/test/ui/nll/issue-52663-span-decl-captured-variable.stderr b/src/test/ui/nll/issue-52663-span-decl-captured-variable.stderr index 67115a5ccdd..c9324f0422c 100644 --- a/src/test/ui/nll/issue-52663-span-decl-captured-variable.stderr +++ b/src/test/ui/nll/issue-52663-span-decl-captured-variable.stderr @@ -4,7 +4,10 @@ error[E0507]: cannot move out of `x.0`, as `x` is a captured variable in an `Fn` LL | let x = (vec![22], vec![44]); | - captured outer variable LL | expect_fn(|| drop(x.0)); - | ^^^ move occurs because `x.0` has type `Vec<i32>`, which does not implement the `Copy` trait + | --------^^^- + | | | + | | move occurs because `x.0` has type `Vec<i32>`, which does not implement the `Copy` trait + | captured by this `Fn` closure error: aborting due to previous error diff --git a/src/test/ui/nll/issue-55394.stderr b/src/test/ui/nll/issue-55394.stderr index 36721f923f7..dbc478e5b4c 100644 --- a/src/test/ui/nll/issue-55394.stderr +++ b/src/test/ui/nll/issue-55394.stderr @@ -19,7 +19,7 @@ note: but, the lifetime must be valid for the lifetime `'_` as defined on the im | LL | impl Foo<'_> { | ^^ -note: ...so that the expression is assignable +note: ...so that the types are compatible --> $DIR/issue-55394.rs:9:9 | LL | Foo { bar } diff --git a/src/test/ui/nll/type-alias-free-regions.stderr b/src/test/ui/nll/type-alias-free-regions.stderr index 6498ecfbe6f..dbb63b71af8 100644 --- a/src/test/ui/nll/type-alias-free-regions.stderr +++ b/src/test/ui/nll/type-alias-free-regions.stderr @@ -21,7 +21,7 @@ note: but, the lifetime must be valid for the lifetime `'a` as defined on the im | LL | impl<'a> FromBox<'a> for C<'a> { | ^^ -note: ...so that the expression is assignable +note: ...so that the types are compatible --> $DIR/type-alias-free-regions.rs:17:9 | LL | C { f: b } @@ -52,7 +52,7 @@ note: but, the lifetime must be valid for the lifetime `'a` as defined on the im | LL | impl<'a> FromTuple<'a> for C<'a> { | ^^ -note: ...so that the expression is assignable +note: ...so that the types are compatible --> $DIR/type-alias-free-regions.rs:27:9 | LL | C { f: Box::new(b.0) } diff --git a/src/test/ui/nll/user-annotations/adt-brace-enums.stderr b/src/test/ui/nll/user-annotations/adt-brace-enums.stderr index e38b77fdcea..253e3825110 100644 --- a/src/test/ui/nll/user-annotations/adt-brace-enums.stderr +++ b/src/test/ui/nll/user-annotations/adt-brace-enums.stderr @@ -5,7 +5,7 @@ LL | SomeEnum::SomeVariant::<&'static u32> { t: &c }; | ^^ | | | borrowed value does not live long enough - | requires that `c` is borrowed for `'static` + | this usage requires that `c` is borrowed for `'static` LL | } | - `c` dropped here while still borrowed @@ -19,7 +19,7 @@ LL | SomeEnum::SomeVariant::<&'a u32> { t: &c }; | ^^ | | | borrowed value does not live long enough - | requires that `c` is borrowed for `'a` + | this usage requires that `c` is borrowed for `'a` LL | } | - `c` dropped here while still borrowed @@ -33,7 +33,7 @@ LL | SomeEnum::SomeVariant::<&'a u32> { t: &c }; | ^^ | | | borrowed value does not live long enough - | requires that `c` is borrowed for `'a` + | this usage requires that `c` is borrowed for `'a` LL | }; | - `c` dropped here while still borrowed diff --git a/src/test/ui/nll/user-annotations/adt-brace-structs.stderr b/src/test/ui/nll/user-annotations/adt-brace-structs.stderr index 3c3003477c2..8b9d1705df6 100644 --- a/src/test/ui/nll/user-annotations/adt-brace-structs.stderr +++ b/src/test/ui/nll/user-annotations/adt-brace-structs.stderr @@ -5,7 +5,7 @@ LL | SomeStruct::<&'static u32> { t: &c }; | ^^ | | | borrowed value does not live long enough - | requires that `c` is borrowed for `'static` + | this usage requires that `c` is borrowed for `'static` LL | } | - `c` dropped here while still borrowed @@ -19,7 +19,7 @@ LL | SomeStruct::<&'a u32> { t: &c }; | ^^ | | | borrowed value does not live long enough - | requires that `c` is borrowed for `'a` + | this usage requires that `c` is borrowed for `'a` LL | } | - `c` dropped here while still borrowed @@ -33,7 +33,7 @@ LL | SomeStruct::<&'a u32> { t: &c }; | ^^ | | | borrowed value does not live long enough - | requires that `c` is borrowed for `'a` + | this usage requires that `c` is borrowed for `'a` LL | }; | - `c` dropped here while still borrowed diff --git a/src/test/ui/nll/user-annotations/adt-tuple-enums.stderr b/src/test/ui/nll/user-annotations/adt-tuple-enums.stderr index 810912bf886..2fa7042631d 100644 --- a/src/test/ui/nll/user-annotations/adt-tuple-enums.stderr +++ b/src/test/ui/nll/user-annotations/adt-tuple-enums.stderr @@ -5,7 +5,7 @@ LL | SomeEnum::SomeVariant::<&'static u32>(&c); | ^^ | | | borrowed value does not live long enough - | requires that `c` is borrowed for `'static` + | this usage requires that `c` is borrowed for `'static` LL | } | - `c` dropped here while still borrowed @@ -19,7 +19,7 @@ LL | SomeEnum::SomeVariant::<&'a u32>(&c); | ^^ | | | borrowed value does not live long enough - | requires that `c` is borrowed for `'a` + | this usage requires that `c` is borrowed for `'a` LL | } | - `c` dropped here while still borrowed @@ -33,7 +33,7 @@ LL | SomeEnum::SomeVariant::<&'a u32>(&c); | ^^ | | | borrowed value does not live long enough - | requires that `c` is borrowed for `'a` + | this usage requires that `c` is borrowed for `'a` LL | }; | - `c` dropped here while still borrowed diff --git a/src/test/ui/nll/user-annotations/adt-tuple-struct.stderr b/src/test/ui/nll/user-annotations/adt-tuple-struct.stderr index 4d2140eca1b..76b5252258c 100644 --- a/src/test/ui/nll/user-annotations/adt-tuple-struct.stderr +++ b/src/test/ui/nll/user-annotations/adt-tuple-struct.stderr @@ -5,7 +5,7 @@ LL | SomeStruct::<&'static u32>(&c); | ^^ | | | borrowed value does not live long enough - | requires that `c` is borrowed for `'static` + | this usage requires that `c` is borrowed for `'static` LL | } | - `c` dropped here while still borrowed @@ -19,7 +19,7 @@ LL | SomeStruct::<&'a u32>(&c); | ^^ | | | borrowed value does not live long enough - | requires that `c` is borrowed for `'a` + | this usage requires that `c` is borrowed for `'a` LL | } | - `c` dropped here while still borrowed @@ -33,7 +33,7 @@ LL | SomeStruct::<&'a u32>(&c); | ^^ | | | borrowed value does not live long enough - | requires that `c` is borrowed for `'a` + | this usage requires that `c` is borrowed for `'a` LL | }; | - `c` dropped here while still borrowed diff --git a/src/test/ui/nll/where_clauses_in_structs.stderr b/src/test/ui/nll/where_clauses_in_structs.stderr index 2e990131e61..8499b00f6f5 100644 --- a/src/test/ui/nll/where_clauses_in_structs.stderr +++ b/src/test/ui/nll/where_clauses_in_structs.stderr @@ -6,7 +6,7 @@ LL | fn bar<'a, 'b>(x: Cell<&'a u32>, y: Cell<&'b u32>) { | | | lifetime `'a` defined here LL | Foo { x, y }; - | ^ requires that `'a` must outlive `'b` + | ^ this usage requires that `'a` must outlive `'b` | = help: consider adding the following bound: `'a: 'b` diff --git a/src/test/ui/numeric/numeric-fields.stderr b/src/test/ui/numeric/numeric-fields.stderr index b328fbe2cfb..668405ed638 100644 --- a/src/test/ui/numeric/numeric-fields.stderr +++ b/src/test/ui/numeric/numeric-fields.stderr @@ -16,7 +16,10 @@ error[E0026]: struct `S` does not have a field named `0x1` --> $DIR/numeric-fields.rs:7:17 | LL | S{0: a, 0x1: b, ..} => {} - | ^^^ struct `S` does not have this field + | ^^^ + | | + | struct `S` does not have this field + | help: `S` has a field named `1` error: aborting due to 2 previous errors diff --git a/src/test/ui/object-lifetime/object-lifetime-default-elision.stderr b/src/test/ui/object-lifetime/object-lifetime-default-elision.stderr index 79ded5fc875..ee1a4612572 100644 --- a/src/test/ui/object-lifetime/object-lifetime-default-elision.stderr +++ b/src/test/ui/object-lifetime/object-lifetime-default-elision.stderr @@ -19,7 +19,7 @@ note: but, the lifetime must be valid for the lifetime `'b` as defined on the fu | LL | fn load3<'a,'b>(ss: &'a dyn SomeTrait) -> &'b dyn SomeTrait { | ^^ -note: ...so that the expression is assignable +note: ...so that the types are compatible --> $DIR/object-lifetime-default-elision.rs:71:5 | LL | ss @@ -48,7 +48,7 @@ note: but, the lifetime must be valid for the lifetime `'b` as defined on the fu | LL | fn load3<'a,'b>(ss: &'a dyn SomeTrait) -> &'b dyn SomeTrait { | ^^ -note: ...so that the expression is assignable +note: ...so that the types are compatible --> $DIR/object-lifetime-default-elision.rs:71:5 | LL | ss diff --git a/src/test/ui/parser/recover-for-loop-parens-around-head.rs b/src/test/ui/parser/recover-for-loop-parens-around-head.rs index 779e1646344..8080dbc332a 100644 --- a/src/test/ui/parser/recover-for-loop-parens-around-head.rs +++ b/src/test/ui/parser/recover-for-loop-parens-around-head.rs @@ -9,7 +9,7 @@ fn main() { for ( elem in vec ) { //~^ ERROR expected one of `)`, `,`, `@`, or `|`, found keyword `in` - //~| ERROR unexpected closing `)` + //~| ERROR unexpected parenthesis surrounding `for` loop head const RECOVERY_WITNESS: () = 0; //~ ERROR mismatched types } } diff --git a/src/test/ui/parser/recover-for-loop-parens-around-head.stderr b/src/test/ui/parser/recover-for-loop-parens-around-head.stderr index e97cf544ac2..21991348327 100644 --- a/src/test/ui/parser/recover-for-loop-parens-around-head.stderr +++ b/src/test/ui/parser/recover-for-loop-parens-around-head.stderr @@ -4,14 +4,17 @@ error: expected one of `)`, `,`, `@`, or `|`, found keyword `in` LL | for ( elem in vec ) { | ^^ expected one of `)`, `,`, `@`, or `|` -error: unexpected closing `)` - --> $DIR/recover-for-loop-parens-around-head.rs:10:23 +error: unexpected parenthesis surrounding `for` loop head + --> $DIR/recover-for-loop-parens-around-head.rs:10:9 | LL | for ( elem in vec ) { - | --------------^ - | | - | opening `(` - | help: remove parenthesis in `for` loop: `elem in vec` + | ^ ^ + | +help: remove parenthesis in `for` loop + | +LL - for ( elem in vec ) { +LL + for elem in vec { + | error[E0308]: mismatched types --> $DIR/recover-for-loop-parens-around-head.rs:13:38 diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr index 1c8840f540e..852ca0f21b1 100644 --- a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr +++ b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr @@ -69,7 +69,7 @@ note: but, the lifetime must be valid for the lifetime `'b` as defined on the fu | LL | fn d<'a,'b>(v: &'a [u8]) -> Box<dyn Foo+'b> { | ^^ -note: ...so that the expression is assignable +note: ...so that the types are compatible --> $DIR/region-object-lifetime-in-coercion.rs:23:5 | LL | Box::new(v) diff --git a/src/test/ui/regions/regions-close-over-type-parameter-multiple.stderr b/src/test/ui/regions/regions-close-over-type-parameter-multiple.stderr index 0cce89215d3..bf29c76a0f0 100644 --- a/src/test/ui/regions/regions-close-over-type-parameter-multiple.stderr +++ b/src/test/ui/regions/regions-close-over-type-parameter-multiple.stderr @@ -19,7 +19,7 @@ note: but, the lifetime must be valid for the lifetime `'c` as defined on the fu | LL | fn make_object_bad<'a,'b,'c,A:SomeTrait+'a+'b>(v: A) -> Box<dyn SomeTrait + 'c> { | ^^ -note: ...so that the expression is assignable +note: ...so that the types are compatible --> $DIR/regions-close-over-type-parameter-multiple.rs:20:5 | LL | box v as Box<dyn SomeTrait + 'a> diff --git a/src/test/ui/regions/regions-creating-enums4.stderr b/src/test/ui/regions/regions-creating-enums4.stderr index b24db1df18b..44bd88e01a2 100644 --- a/src/test/ui/regions/regions-creating-enums4.stderr +++ b/src/test/ui/regions/regions-creating-enums4.stderr @@ -21,7 +21,7 @@ note: but, the lifetime must be valid for the lifetime `'b` as defined on the fu | LL | fn mk_add_bad2<'a,'b>(x: &'a Ast<'a>, y: &'a Ast<'a>, z: &Ast) -> Ast<'b> { | ^^ -note: ...so that the expression is assignable +note: ...so that the types are compatible --> $DIR/regions-creating-enums4.rs:7:5 | LL | Ast::Add(x, y) diff --git a/src/test/ui/regions/regions-ret-borrowed-1.stderr b/src/test/ui/regions/regions-ret-borrowed-1.stderr index bba968cfde4..b5b54bc3c8b 100644 --- a/src/test/ui/regions/regions-ret-borrowed-1.stderr +++ b/src/test/ui/regions/regions-ret-borrowed-1.stderr @@ -9,7 +9,7 @@ note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on th | LL | with(|o| o) | ^^^^^ -note: ...so that the expression is assignable +note: ...so that the types are compatible --> $DIR/regions-ret-borrowed-1.rs:10:14 | LL | with(|o| o) diff --git a/src/test/ui/regions/regions-ret-borrowed.stderr b/src/test/ui/regions/regions-ret-borrowed.stderr index 4b93ca0ae67..debae47d16d 100644 --- a/src/test/ui/regions/regions-ret-borrowed.stderr +++ b/src/test/ui/regions/regions-ret-borrowed.stderr @@ -9,7 +9,7 @@ note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on th | LL | with(|o| o) | ^^^^^ -note: ...so that the expression is assignable +note: ...so that the types are compatible --> $DIR/regions-ret-borrowed.rs:13:14 | LL | with(|o| o) diff --git a/src/test/ui/regions/regions-trait-object-subtyping.stderr b/src/test/ui/regions/regions-trait-object-subtyping.stderr index 7478b53bd3c..f16dfdd6e8c 100644 --- a/src/test/ui/regions/regions-trait-object-subtyping.stderr +++ b/src/test/ui/regions/regions-trait-object-subtyping.stderr @@ -36,7 +36,7 @@ note: but, the lifetime must be valid for the lifetime `'b` as defined on the fu | LL | fn foo3<'a,'b>(x: &'a mut dyn Dummy) -> &'b mut dyn Dummy { | ^^ -note: ...so that the expression is assignable +note: ...so that the types are compatible --> $DIR/regions-trait-object-subtyping.rs:15:5 | LL | x diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-shuffle.rs b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-shuffle.rs new file mode 100644 index 00000000000..9611780ac07 --- /dev/null +++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-shuffle.rs @@ -0,0 +1,33 @@ +// build-fail + +// Test that the simd_shuffle intrinsic produces ok-ish error +// messages when misused. + +#![feature(repr_simd, platform_intrinsics)] + +#[repr(simd)] +#[derive(Copy, Clone)] +pub struct Simd<T, const N: usize>([T; N]); + +extern "platform-intrinsic" { + fn simd_shuffle<T, I, U>(a: T, b: T, i: I) -> U; +} + +fn main() { + const I: [u32; 2] = [0; 2]; + const I2: [f32; 2] = [0.; 2]; + let v = Simd::<u32, 4>([0; 4]); + + unsafe { + let _: Simd<u32, 2> = simd_shuffle(v, v, I); + + let _: Simd<u32, 4> = simd_shuffle(v, v, I); + //~^ ERROR invalid monomorphization of `simd_shuffle` intrinsic + + let _: Simd<f32, 2> = simd_shuffle(v, v, I); + //~^ ERROR invalid monomorphization of `simd_shuffle` intrinsic + + let _: Simd<u32, 2> = simd_shuffle(v, v, I2); + //~^ ERROR invalid monomorphization of `simd_shuffle` intrinsic + } +} diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-shuffle.stderr b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-shuffle.stderr new file mode 100644 index 00000000000..9eeb000fd26 --- /dev/null +++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-shuffle.stderr @@ -0,0 +1,21 @@ +error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return type of length 2, found `Simd<u32, 4_usize>` with length 4 + --> $DIR/simd-intrinsic-generic-shuffle.rs:24:31 + | +LL | let _: Simd<u32, 4> = simd_shuffle(v, v, I); + | ^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return element type `u32` (element of input `Simd<u32, 4_usize>`), found `Simd<f32, 2_usize>` with element type `f32` + --> $DIR/simd-intrinsic-generic-shuffle.rs:27:31 + | +LL | let _: Simd<f32, 2> = simd_shuffle(v, v, I); + | ^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: simd_shuffle index must be an array of `u32`, got `[f32; 2]` + --> $DIR/simd-intrinsic-generic-shuffle.rs:30:31 + | +LL | let _: Simd<u32, 2> = simd_shuffle(v, v, I2); + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0511`. diff --git a/src/test/ui/simd/monomorphize-shuffle-index.rs b/src/test/ui/simd/monomorphize-shuffle-index.rs new file mode 100644 index 00000000000..2467baa08b0 --- /dev/null +++ b/src/test/ui/simd/monomorphize-shuffle-index.rs @@ -0,0 +1,40 @@ +//run-pass +#![feature(repr_simd, platform_intrinsics)] + +extern "platform-intrinsic" { + fn simd_shuffle<T, I, U>(a: T, b: T, i: I) -> U; +} + +#[derive(Copy, Clone)] +#[repr(simd)] +struct Simd<T, const N: usize>([T; N]); + +trait Shuffle<const N: usize> { + const I: [u32; N]; + + unsafe fn shuffle<T, const M: usize>(&self, a: Simd<T, M>, b: Simd<T, M>) -> Simd<T, N> { + simd_shuffle(a, b, Self::I) + } +} + +fn main() { + struct I1; + impl Shuffle<4> for I1 { + const I: [u32; 4] = [0, 2, 4, 6]; + } + + struct I2; + impl Shuffle<2> for I2 { + const I: [u32; 2] = [1, 5]; + } + + let a = Simd::<u8, 4>([0, 1, 2, 3]); + let b = Simd::<u8, 4>([4, 5, 6, 7]); + unsafe { + let x: Simd<u8, 4> = I1.shuffle(a, b); + assert_eq!(x.0, [0, 2, 4, 6]); + + let y: Simd<u8, 2> = I2.shuffle(a, b); + assert_eq!(y.0, [1, 5]); + } +} diff --git a/src/test/ui/simd/shuffle-not-out-of-bounds.rs b/src/test/ui/simd/shuffle-not-out-of-bounds.rs index 8a533453e75..aae6ce4663f 100644 --- a/src/test/ui/simd/shuffle-not-out-of-bounds.rs +++ b/src/test/ui/simd/shuffle-not-out-of-bounds.rs @@ -188,4 +188,14 @@ fn main() { 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)); + + extern "platform-intrinsic" { + fn simd_shuffle<T, I, U>(a: T, b: T, i: I) -> U; + } + let v = u8x2(0, 0); + const I: [u32; 2] = [4, 4]; + unsafe { + let _: u8x2 = simd_shuffle(v, v, I); + //~^ ERROR invalid monomorphization of `simd_shuffle` intrinsic + } } diff --git a/src/test/ui/simd/shuffle-not-out-of-bounds.stderr b/src/test/ui/simd/shuffle-not-out-of-bounds.stderr index 07253a4ae46..737fb5e6e51 100644 --- a/src/test/ui/simd/shuffle-not-out-of-bounds.stderr +++ b/src/test/ui/simd/shuffle-not-out-of-bounds.stderr @@ -71,6 +71,12 @@ LL | | 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)); | = note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 6 previous errors +error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: shuffle index #0 is out of bounds (limit 4) + --> $DIR/shuffle-not-out-of-bounds.rs:198:23 + | +LL | let _: u8x2 = simd_shuffle(v, v, I); + | ^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0511`. diff --git a/src/test/ui/simd/shuffle.rs b/src/test/ui/simd/shuffle.rs new file mode 100644 index 00000000000..3592adfdc6a --- /dev/null +++ b/src/test/ui/simd/shuffle.rs @@ -0,0 +1,24 @@ +//run-pass +#![feature(repr_simd, platform_intrinsics)] + +extern "platform-intrinsic" { + fn simd_shuffle<T, I, U>(a: T, b: T, i: I) -> U; +} + +#[derive(Copy, Clone)] +#[repr(simd)] +struct Simd<T, const N: usize>([T; N]); + +fn main() { + const I1: [u32; 4] = [0, 2, 4, 6]; + const I2: [u32; 2] = [1, 5]; + let a = Simd::<u8, 4>([0, 1, 2, 3]); + let b = Simd::<u8, 4>([4, 5, 6, 7]); + unsafe { + let x: Simd<u8, 4> = simd_shuffle(a, b, I1); + assert_eq!(x.0, [0, 2, 4, 6]); + + let y: Simd<u8, 2> = simd_shuffle(a, b, I2); + assert_eq!(y.0, [1, 5]); + } +} diff --git a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr index ab1fa2a4d87..0f630abd148 100644 --- a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr +++ b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr @@ -29,11 +29,17 @@ LL | f.f.call_mut(()) error[E0507]: cannot move out of `f`, a captured variable in an `FnMut` closure --> $DIR/borrowck-call-is-borrow-issue-12224.rs:57:13 | -LL | let mut f = move |g: Box<dyn FnMut(isize)>, b: isize| { - | ----- captured outer variable +LL | let mut f = move |g: Box<dyn FnMut(isize)>, b: isize| { + | ----- captured outer variable ... -LL | foo(f); - | ^ move occurs because `f` has type `[closure@$DIR/borrowck-call-is-borrow-issue-12224.rs:52:17: 54:6]`, which does not implement the `Copy` trait +LL | f(Box::new(|a| { + | ________________- +LL | | +LL | | foo(f); + | | ^ move occurs because `f` has type `[closure@$DIR/borrowck-call-is-borrow-issue-12224.rs:52:17: 54:6]`, which does not implement the `Copy` trait +LL | | +LL | | }), 3); + | |_____- captured by this `FnMut` closure error[E0505]: cannot move out of `f` because it is borrowed --> $DIR/borrowck-call-is-borrow-issue-12224.rs:55:16 diff --git a/src/test/ui/suggestions/dont-suggest-ref/move-into-closure.stderr b/src/test/ui/suggestions/dont-suggest-ref/move-into-closure.stderr index c50cbcde855..fb1055c9c30 100644 --- a/src/test/ui/suggestions/dont-suggest-ref/move-into-closure.stderr +++ b/src/test/ui/suggestions/dont-suggest-ref/move-into-closure.stderr @@ -1,281 +1,487 @@ error[E0507]: cannot move out of `x.0`, as `x` is a captured variable in an `Fn` closure --> $DIR/move-into-closure.rs:28:21 | -LL | let x = X(Y); - | - captured outer variable +LL | let x = X(Y); + | - captured outer variable ... -LL | let X(_t) = x; - | -- ^ help: consider borrowing here: `&x` - | | - | data moved here - | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait +LL | consume_fn(|| { + | ________________- +LL | | let X(_t) = x; + | | -- ^ help: consider borrowing here: `&x` + | | | + | | data moved here + | | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait +LL | | +LL | | +... | +LL | | } +LL | | }); + | |_____- captured by this `Fn` closure error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `Fn` closure --> $DIR/move-into-closure.rs:32:34 | -LL | let e = Either::One(X(Y)); - | - captured outer variable +LL | let e = Either::One(X(Y)); + | - captured outer variable ... -LL | if let Either::One(_t) = e { } - | -- ^ help: consider borrowing here: `&e` - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +LL | consume_fn(|| { + | ________________- +LL | | let X(_t) = x; +LL | | +LL | | +LL | | +LL | | if let Either::One(_t) = e { } + | | -- ^ help: consider borrowing here: `&e` + | | | + | | data moved here + | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +... | +LL | | } +LL | | }); + | |_____- captured by this `Fn` closure error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `Fn` closure --> $DIR/move-into-closure.rs:36:37 | -LL | let e = Either::One(X(Y)); - | - captured outer variable +LL | let e = Either::One(X(Y)); + | - captured outer variable ... -LL | while let Either::One(_t) = e { } - | -- ^ help: consider borrowing here: `&e` - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +LL | consume_fn(|| { + | ________________- +LL | | let X(_t) = x; +LL | | +LL | | +... | +LL | | while let Either::One(_t) = e { } + | | -- ^ help: consider borrowing here: `&e` + | | | + | | data moved here + | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +... | +LL | | } +LL | | }); + | |_____- captured by this `Fn` closure error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `Fn` closure --> $DIR/move-into-closure.rs:40:15 | -LL | let e = Either::One(X(Y)); - | - captured outer variable +LL | let e = Either::One(X(Y)); + | - captured outer variable ... -LL | match e { - | ^ help: consider borrowing here: `&e` -... -LL | Either::One(_t) - | -- - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +LL | consume_fn(|| { + | ________________- +LL | | let X(_t) = x; +LL | | +LL | | +... | +LL | | match e { + | | ^ help: consider borrowing here: `&e` +... | +LL | | Either::One(_t) + | | -- + | | | + | | data moved here + | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +... | +LL | | } +LL | | }); + | |_____- captured by this `Fn` closure error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `Fn` closure --> $DIR/move-into-closure.rs:47:15 | -LL | let e = Either::One(X(Y)); - | - captured outer variable -... -LL | match e { - | ^ help: consider borrowing here: `&e` +LL | let e = Either::One(X(Y)); + | - captured outer variable ... -LL | Either::One(_t) => (), - | -- - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +LL | consume_fn(|| { + | ________________- +LL | | let X(_t) = x; +LL | | +LL | | +... | +LL | | match e { + | | ^ help: consider borrowing here: `&e` +... | +LL | | Either::One(_t) => (), + | | -- + | | | + | | data moved here + | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +... | +LL | | } +LL | | }); + | |_____- captured by this `Fn` closure error[E0507]: cannot move out of `x.0`, as `x` is a captured variable in an `Fn` closure --> $DIR/move-into-closure.rs:56:25 | -LL | let x = X(Y); - | - captured outer variable +LL | let x = X(Y); + | - captured outer variable ... -LL | let X(mut _t) = x; - | ------ ^ help: consider borrowing here: `&x` - | | - | data moved here - | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait +LL | consume_fn(|| { + | ________________- +LL | | let X(_t) = x; +LL | | +LL | | +... | +LL | | let X(mut _t) = x; + | | ------ ^ help: consider borrowing here: `&x` + | | | + | | data moved here + | | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait +... | +LL | | } +LL | | }); + | |_____- captured by this `Fn` closure error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `Fn` closure --> $DIR/move-into-closure.rs:60:38 | -LL | let mut em = Either::One(X(Y)); - | ------ captured outer variable +LL | let mut em = Either::One(X(Y)); + | ------ captured outer variable ... -LL | if let Either::One(mut _t) = em { } - | ------ ^^ help: consider borrowing here: `&em` - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +LL | consume_fn(|| { + | ________________- +LL | | let X(_t) = x; +LL | | +LL | | +... | +LL | | if let Either::One(mut _t) = em { } + | | ------ ^^ help: consider borrowing here: `&em` + | | | + | | data moved here + | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +... | +LL | | } +LL | | }); + | |_____- captured by this `Fn` closure error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `Fn` closure --> $DIR/move-into-closure.rs:64:41 | -LL | let mut em = Either::One(X(Y)); - | ------ captured outer variable +LL | let mut em = Either::One(X(Y)); + | ------ captured outer variable ... -LL | while let Either::One(mut _t) = em { } - | ------ ^^ help: consider borrowing here: `&em` - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +LL | consume_fn(|| { + | ________________- +LL | | let X(_t) = x; +LL | | +LL | | +... | +LL | | while let Either::One(mut _t) = em { } + | | ------ ^^ help: consider borrowing here: `&em` + | | | + | | data moved here + | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +... | +LL | | } +LL | | }); + | |_____- captured by this `Fn` closure error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `Fn` closure --> $DIR/move-into-closure.rs:68:15 | -LL | let mut em = Either::One(X(Y)); - | ------ captured outer variable -... -LL | match em { - | ^^ help: consider borrowing here: `&em` +LL | let mut em = Either::One(X(Y)); + | ------ captured outer variable ... -LL | Either::One(mut _t) - | ------ - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +LL | consume_fn(|| { + | ________________- +LL | | let X(_t) = x; +LL | | +LL | | +... | +LL | | match em { + | | ^^ help: consider borrowing here: `&em` +... | +LL | | Either::One(mut _t) + | | ------ + | | | + | | data moved here + | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +... | +LL | | } +LL | | }); + | |_____- captured by this `Fn` closure error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `Fn` closure --> $DIR/move-into-closure.rs:75:15 | -LL | let mut em = Either::One(X(Y)); - | ------ captured outer variable +LL | let mut em = Either::One(X(Y)); + | ------ captured outer variable ... -LL | match em { - | ^^ help: consider borrowing here: `&em` -... -LL | Either::One(mut _t) => (), - | ------ - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +LL | consume_fn(|| { + | ________________- +LL | | let X(_t) = x; +LL | | +LL | | +... | +LL | | match em { + | | ^^ help: consider borrowing here: `&em` +... | +LL | | Either::One(mut _t) => (), + | | ------ + | | | + | | data moved here + | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +... | +LL | | } +LL | | }); + | |_____- captured by this `Fn` closure error[E0507]: cannot move out of `x.0`, as `x` is a captured variable in an `FnMut` closure --> $DIR/move-into-closure.rs:95:21 | -LL | let x = X(Y); - | - captured outer variable +LL | let x = X(Y); + | - captured outer variable ... -LL | let X(_t) = x; - | -- ^ help: consider borrowing here: `&x` - | | - | data moved here - | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait +LL | consume_fnmut(|| { + | ___________________- +LL | | let X(_t) = x; + | | -- ^ help: consider borrowing here: `&x` + | | | + | | data moved here + | | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait +LL | | +LL | | +... | +LL | | } +LL | | }); + | |_____- captured by this `FnMut` closure error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `FnMut` closure --> $DIR/move-into-closure.rs:99:34 | -LL | let e = Either::One(X(Y)); - | - captured outer variable +LL | let e = Either::One(X(Y)); + | - captured outer variable ... -LL | if let Either::One(_t) = e { } - | -- ^ help: consider borrowing here: `&e` - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +LL | consume_fnmut(|| { + | ___________________- +LL | | let X(_t) = x; +LL | | +LL | | +LL | | +LL | | if let Either::One(_t) = e { } + | | -- ^ help: consider borrowing here: `&e` + | | | + | | data moved here + | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +... | +LL | | } +LL | | }); + | |_____- captured by this `FnMut` closure error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `FnMut` closure --> $DIR/move-into-closure.rs:103:37 | -LL | let e = Either::One(X(Y)); - | - captured outer variable +LL | let e = Either::One(X(Y)); + | - captured outer variable ... -LL | while let Either::One(_t) = e { } - | -- ^ help: consider borrowing here: `&e` - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +LL | consume_fnmut(|| { + | ___________________- +LL | | let X(_t) = x; +LL | | +LL | | +... | +LL | | while let Either::One(_t) = e { } + | | -- ^ help: consider borrowing here: `&e` + | | | + | | data moved here + | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +... | +LL | | } +LL | | }); + | |_____- captured by this `FnMut` closure error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `FnMut` closure --> $DIR/move-into-closure.rs:107:15 | -LL | let e = Either::One(X(Y)); - | - captured outer variable -... -LL | match e { - | ^ help: consider borrowing here: `&e` +LL | let e = Either::One(X(Y)); + | - captured outer variable ... -LL | Either::One(_t) - | -- - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +LL | consume_fnmut(|| { + | ___________________- +LL | | let X(_t) = x; +LL | | +LL | | +... | +LL | | match e { + | | ^ help: consider borrowing here: `&e` +... | +LL | | Either::One(_t) + | | -- + | | | + | | data moved here + | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +... | +LL | | } +LL | | }); + | |_____- captured by this `FnMut` closure error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `FnMut` closure --> $DIR/move-into-closure.rs:114:15 | -LL | let e = Either::One(X(Y)); - | - captured outer variable +LL | let e = Either::One(X(Y)); + | - captured outer variable ... -LL | match e { - | ^ help: consider borrowing here: `&e` -... -LL | Either::One(_t) => (), - | -- - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +LL | consume_fnmut(|| { + | ___________________- +LL | | let X(_t) = x; +LL | | +LL | | +... | +LL | | match e { + | | ^ help: consider borrowing here: `&e` +... | +LL | | Either::One(_t) => (), + | | -- + | | | + | | data moved here + | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +... | +LL | | } +LL | | }); + | |_____- captured by this `FnMut` closure error[E0507]: cannot move out of `x.0`, as `x` is a captured variable in an `FnMut` closure --> $DIR/move-into-closure.rs:123:25 | -LL | let x = X(Y); - | - captured outer variable +LL | let x = X(Y); + | - captured outer variable ... -LL | let X(mut _t) = x; - | ------ ^ help: consider borrowing here: `&x` - | | - | data moved here - | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait +LL | consume_fnmut(|| { + | ___________________- +LL | | let X(_t) = x; +LL | | +LL | | +... | +LL | | let X(mut _t) = x; + | | ------ ^ help: consider borrowing here: `&x` + | | | + | | data moved here + | | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait +... | +LL | | } +LL | | }); + | |_____- captured by this `FnMut` closure error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure --> $DIR/move-into-closure.rs:127:38 | -LL | let mut em = Either::One(X(Y)); - | ------ captured outer variable +LL | let mut em = Either::One(X(Y)); + | ------ captured outer variable ... -LL | if let Either::One(mut _t) = em { } - | ------ ^^ help: consider borrowing here: `&em` - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +LL | consume_fnmut(|| { + | ___________________- +LL | | let X(_t) = x; +LL | | +LL | | +... | +LL | | if let Either::One(mut _t) = em { } + | | ------ ^^ help: consider borrowing here: `&em` + | | | + | | data moved here + | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +... | +LL | | } +LL | | }); + | |_____- captured by this `FnMut` closure error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure --> $DIR/move-into-closure.rs:131:41 | -LL | let mut em = Either::One(X(Y)); - | ------ captured outer variable +LL | let mut em = Either::One(X(Y)); + | ------ captured outer variable ... -LL | while let Either::One(mut _t) = em { } - | ------ ^^ help: consider borrowing here: `&em` - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +LL | consume_fnmut(|| { + | ___________________- +LL | | let X(_t) = x; +LL | | +LL | | +... | +LL | | while let Either::One(mut _t) = em { } + | | ------ ^^ help: consider borrowing here: `&em` + | | | + | | data moved here + | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +... | +LL | | } +LL | | }); + | |_____- captured by this `FnMut` closure error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure --> $DIR/move-into-closure.rs:135:15 | -LL | let mut em = Either::One(X(Y)); - | ------ captured outer variable -... -LL | match em { - | ^^ help: consider borrowing here: `&em` +LL | let mut em = Either::One(X(Y)); + | ------ captured outer variable ... -LL | Either::One(mut _t) - | ------ - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +LL | consume_fnmut(|| { + | ___________________- +LL | | let X(_t) = x; +LL | | +LL | | +... | +LL | | match em { + | | ^^ help: consider borrowing here: `&em` +... | +LL | | Either::One(mut _t) + | | ------ + | | | + | | data moved here + | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +... | +LL | | } +LL | | }); + | |_____- captured by this `FnMut` closure error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure --> $DIR/move-into-closure.rs:142:15 | -LL | let mut em = Either::One(X(Y)); - | ------ captured outer variable +LL | let mut em = Either::One(X(Y)); + | ------ captured outer variable ... -LL | match em { - | ^^ help: consider borrowing here: `&em` -... -LL | Either::One(mut _t) => (), - | ------ - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +LL | consume_fnmut(|| { + | ___________________- +LL | | let X(_t) = x; +LL | | +LL | | +... | +LL | | match em { + | | ^^ help: consider borrowing here: `&em` +... | +LL | | Either::One(mut _t) => (), + | | ------ + | | | + | | data moved here + | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +... | +LL | | } +LL | | }); + | |_____- captured by this `FnMut` closure error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure --> $DIR/move-into-closure.rs:150:15 | -LL | let mut em = Either::One(X(Y)); - | ------ captured outer variable -... -LL | match em { - | ^^ help: consider borrowing here: `&em` +LL | let mut em = Either::One(X(Y)); + | ------ captured outer variable ... -LL | Either::One(mut _t) => (), - | ------ - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +LL | consume_fnmut(|| { + | ___________________- +LL | | let X(_t) = x; +LL | | +LL | | +... | +LL | | match em { + | | ^^ help: consider borrowing here: `&em` +... | +LL | | Either::One(mut _t) => (), + | | ------ + | | | + | | data moved here + | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +... | +LL | | } +LL | | }); + | |_____- captured by this `FnMut` closure error: aborting due to 21 previous errors diff --git a/src/test/ui/suggestions/option-content-move2.stderr b/src/test/ui/suggestions/option-content-move2.stderr index cfbee1518cd..a0ce7d05b4d 100644 --- a/src/test/ui/suggestions/option-content-move2.stderr +++ b/src/test/ui/suggestions/option-content-move2.stderr @@ -1,17 +1,22 @@ error[E0507]: cannot move out of `var`, a captured variable in an `FnMut` closure --> $DIR/option-content-move2.rs:9:9 | -LL | let mut var = None; - | ------- captured outer variable -... -LL | move || { - | ^^^^^^^ move out of `var` occurs here -LL | -LL | var = Some(NotCopyable); - | --- - | | - | move occurs because `var` has type `Option<NotCopyable>`, which does not implement the `Copy` trait - | move occurs due to use in closure +LL | let mut var = None; + | ------- captured outer variable +LL | func(|| { + | __________- +LL | | // Shouldn't suggest `move ||.as_ref()` here +LL | | move || { + | | ^^^^^^^ move out of `var` occurs here +LL | | +LL | | var = Some(NotCopyable); + | | --- + | | | + | | move occurs because `var` has type `Option<NotCopyable>`, which does not implement the `Copy` trait + | | move occurs due to use in closure +LL | | } +LL | | }); + | |_____- captured by this `FnMut` closure error: aborting due to previous error diff --git a/src/test/ui/typeck/issue-88844.rs b/src/test/ui/typeck/issue-88844.rs new file mode 100644 index 00000000000..116c75aabdb --- /dev/null +++ b/src/test/ui/typeck/issue-88844.rs @@ -0,0 +1,14 @@ +// Regression test for #88844. + +struct Struct { value: i32 } +//~^ NOTE: similarly named struct `Struct` defined here + +impl Stuct { +//~^ ERROR: cannot find type `Stuct` in this scope [E0412] +//~| HELP: a struct with a similar name exists + fn new() -> Self { + Self { value: 42 } + } +} + +fn main() {} diff --git a/src/test/ui/typeck/issue-88844.stderr b/src/test/ui/typeck/issue-88844.stderr new file mode 100644 index 00000000000..90bba90be34 --- /dev/null +++ b/src/test/ui/typeck/issue-88844.stderr @@ -0,0 +1,12 @@ +error[E0412]: cannot find type `Stuct` in this scope + --> $DIR/issue-88844.rs:6:6 + | +LL | struct Struct { value: i32 } + | ------------- similarly named struct `Struct` defined here +... +LL | impl Stuct { + | ^^^^^ help: a struct with a similar name exists: `Struct` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/src/test/ui/typeck/issue-89044-wrapped-expr-method.fixed b/src/test/ui/typeck/issue-89044-wrapped-expr-method.fixed new file mode 100644 index 00000000000..0a3086a345d --- /dev/null +++ b/src/test/ui/typeck/issue-89044-wrapped-expr-method.fixed @@ -0,0 +1,9 @@ +// run-rustfix + +fn main() { + let a = Some(42); + println!( + "The value is {}.", + (a.unwrap()) //~ERROR [E0615] + ); +} diff --git a/src/test/ui/typeck/issue-89044-wrapped-expr-method.rs b/src/test/ui/typeck/issue-89044-wrapped-expr-method.rs new file mode 100644 index 00000000000..83617e035e9 --- /dev/null +++ b/src/test/ui/typeck/issue-89044-wrapped-expr-method.rs @@ -0,0 +1,9 @@ +// run-rustfix + +fn main() { + let a = Some(42); + println!( + "The value is {}.", + (a.unwrap) //~ERROR [E0615] + ); +} diff --git a/src/test/ui/typeck/issue-89044-wrapped-expr-method.stderr b/src/test/ui/typeck/issue-89044-wrapped-expr-method.stderr new file mode 100644 index 00000000000..6fa0915dcaf --- /dev/null +++ b/src/test/ui/typeck/issue-89044-wrapped-expr-method.stderr @@ -0,0 +1,14 @@ +error[E0615]: attempted to take value of method `unwrap` on type `Option<{integer}>` + --> $DIR/issue-89044-wrapped-expr-method.rs:7:12 + | +LL | (a.unwrap) + | ^^^^^^ method, not a field + | +help: use parentheses to call the method + | +LL | (a.unwrap()) + | ++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0615`. diff --git a/src/test/ui/unboxed-closures/unboxed-closure-illegal-move.stderr b/src/test/ui/unboxed-closures/unboxed-closure-illegal-move.stderr index f8c90176ff1..482d3e44fe4 100644 --- a/src/test/ui/unboxed-closures/unboxed-closure-illegal-move.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closure-illegal-move.stderr @@ -4,7 +4,10 @@ error[E0507]: cannot move out of `x`, a captured variable in an `Fn` closure LL | let x = Box::new(0); | - captured outer variable LL | let f = to_fn(|| drop(x)); - | ^ move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait + | --------^- + | | | + | | move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait + | captured by this `Fn` closure error[E0507]: cannot move out of `x`, a captured variable in an `FnMut` closure --> $DIR/unboxed-closure-illegal-move.rs:19:35 @@ -12,7 +15,10 @@ error[E0507]: cannot move out of `x`, a captured variable in an `FnMut` closure LL | let x = Box::new(0); | - captured outer variable LL | let f = to_fn_mut(|| drop(x)); - | ^ move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait + | --------^- + | | | + | | move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait + | captured by this `FnMut` closure error[E0507]: cannot move out of `x`, a captured variable in an `Fn` closure --> $DIR/unboxed-closure-illegal-move.rs:28:36 @@ -20,7 +26,10 @@ error[E0507]: cannot move out of `x`, a captured variable in an `Fn` closure LL | let x = Box::new(0); | - captured outer variable LL | let f = to_fn(move || drop(x)); - | ^ move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait + | -------------^- + | | | + | | move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait + | captured by this `Fn` closure error[E0507]: cannot move out of `x`, a captured variable in an `FnMut` closure --> $DIR/unboxed-closure-illegal-move.rs:32:40 @@ -28,7 +37,10 @@ error[E0507]: cannot move out of `x`, a captured variable in an `FnMut` closure LL | let x = Box::new(0); | - captured outer variable LL | let f = to_fn_mut(move || drop(x)); - | ^ move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait + | -------------^- + | | | + | | move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait + | captured by this `FnMut` closure error: aborting due to 4 previous errors diff --git a/src/tools/cargo b/src/tools/cargo -Subproject e515c3277bf0681bfc79a9e763861bfe26bb05d +Subproject 9a28ac83c9eb73e42ffafac552c0a55f00dbf40 diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 5f1267fc3d2..60703384e9e 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -144,6 +144,7 @@ const PERMITTED_DEPENDENCIES: &[&str] = &[ "num-integer", "num-traits", "object", + "odht", "once_cell", "opaque-debug", "parking_lot", |
