diff options
Diffstat (limited to 'compiler')
119 files changed, 928 insertions, 552 deletions
diff --git a/compiler/rustc/Cargo.toml b/compiler/rustc/Cargo.toml index 37f90bf3c10..277cf0f51d3 100644 --- a/compiler/rustc/Cargo.toml +++ b/compiler/rustc/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc-main" version = "0.0.0" -edition = '2018' +edition = "2021" [dependencies] rustc_driver = { path = "../rustc_driver" } diff --git a/compiler/rustc_apfloat/Cargo.toml b/compiler/rustc_apfloat/Cargo.toml index 9f266b1fb97..bb01d4f51b8 100644 --- a/compiler/rustc_apfloat/Cargo.toml +++ b/compiler/rustc_apfloat/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_apfloat" version = "0.0.0" -edition = "2018" +edition = "2021" [dependencies] bitflags = "1.2.1" diff --git a/compiler/rustc_arena/Cargo.toml b/compiler/rustc_arena/Cargo.toml index eba8a2a082f..33ccd044503 100644 --- a/compiler/rustc_arena/Cargo.toml +++ b/compiler/rustc_arena/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_arena" version = "0.0.0" -edition = "2018" +edition = "2021" [dependencies] rustc_data_structures = { path = "../rustc_data_structures" } diff --git a/compiler/rustc_ast/Cargo.toml b/compiler/rustc_ast/Cargo.toml index 67cf5d92b00..58b967a3704 100644 --- a/compiler/rustc_ast/Cargo.toml +++ b/compiler/rustc_ast/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_ast" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] doctest = false diff --git a/compiler/rustc_ast_lowering/Cargo.toml b/compiler/rustc_ast_lowering/Cargo.toml index 4e848a6a2b8..f4859ee4ae9 100644 --- a/compiler/rustc_ast_lowering/Cargo.toml +++ b/compiler/rustc_ast_lowering/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_ast_lowering" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] doctest = false diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index ac7145bed78..a6ea4aa8923 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -55,7 +55,6 @@ impl<'hir> LoweringContext<'_, 'hir> { 0, ParenthesizedGenericArgs::Err, ImplTraitContext::disallowed(), - None, )); let args = self.lower_exprs(args); hir::ExprKind::MethodCall( @@ -328,7 +327,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let mut generic_args = vec![]; for (idx, arg) in args.into_iter().enumerate() { if legacy_args_idx.contains(&idx) { - let parent_def_id = self.current_hir_id_owner.0; + let parent_def_id = self.current_hir_id_owner; let node_id = self.resolver.next_node_id(); // Add a definition for the in-band const def. diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 980036c662a..25e6fed68b5 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -40,12 +40,9 @@ 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); - lctx.insert_item(hir_item) - }) + let node = lctx.without_in_scope_lifetime_defs(|lctx| lctx.lower_item(item)); + hir::OwnerNode::Item(node) }); self.lctx.with_parent_item_lifetime_defs(hir_id, |this| { @@ -72,26 +69,17 @@ 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); - lctx.insert_trait_item(hir_item); - } - AssocCtxt::Impl => { - let hir_item = lctx.lower_impl_item(item); - lctx.insert_impl_item(hir_item); - } + AssocCtxt::Trait => hir::OwnerNode::TraitItem(lctx.lower_trait_item(item)), + AssocCtxt::Impl => hir::OwnerNode::ImplItem(lctx.lower_impl_item(item)), }); visit::walk_assoc_item(self, item, ctxt); } fn visit_foreign_item(&mut self, item: &'a ForeignItem) { - self.lctx.allocate_hir_id_counter(item.id); self.lctx.with_hir_id_owner(item.id, |lctx| { - let hir_item = lctx.lower_foreign_item(item); - lctx.insert_foreign_item(hir_item); + hir::OwnerNode::ForeignItem(lctx.lower_foreign_item(item)) }); visit::walk_foreign_item(self, item); @@ -106,12 +94,12 @@ impl<'hir> LoweringContext<'_, 'hir> { // only used when lowering a child item of a trait or impl. fn with_parent_item_lifetime_defs<T>( &mut self, - parent_hir_id: hir::ItemId, + parent_hir_id: LocalDefId, f: impl FnOnce(&mut Self) -> T, ) -> T { let old_len = self.in_scope_lifetimes.len(); - let parent_generics = match self.owners[parent_hir_id.def_id].unwrap().expect_item().kind { + let parent_generics = match self.owners[parent_hir_id].unwrap().expect_item().kind { hir::ItemKind::Impl(hir::Impl { ref generics, .. }) | hir::ItemKind::Trait(_, _, ref generics, ..) => generics.params, _ => &[], @@ -186,19 +174,20 @@ impl<'hir> LoweringContext<'_, 'hir> { } } - pub fn lower_item(&mut self, i: &Item) -> hir::Item<'hir> { + fn lower_item(&mut self, i: &Item) -> &'hir hir::Item<'hir> { let mut ident = i.ident; - let mut vis = self.lower_visibility(&i.vis, None); + let mut vis = self.lower_visibility(&i.vis); let hir_id = self.lower_node_id(i.id); let attrs = self.lower_attrs(hir_id, &i.attrs); let kind = self.lower_item_kind(i.span, i.id, hir_id, &mut ident, attrs, &mut vis, &i.kind); - hir::Item { + let item = hir::Item { def_id: hir_id.expect_owner(), ident: self.lower_ident(ident), kind, vis, span: self.lower_span(i.span), - } + }; + self.arena.alloc(item) } fn lower_item_kind( @@ -480,10 +469,16 @@ impl<'hir> LoweringContext<'_, 'hir> { // Essentially a single `use` which imports two names is desugared into // two imports. 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 new_id = self.resolver.local_def_id(new_node_id); + let res = if let Some(res) = resolutions.next() { + res + } else { + // Associate an HirId to both ids even if there is no resolution. + self.node_id_to_hir_id.ensure_contains_elem(new_node_id, || None); + debug_assert!(self.node_id_to_hir_id[new_node_id].is_none()); + self.node_id_to_hir_id[new_node_id] = Some(hir::HirId::make_owner(new_id)); + continue; + }; let ident = *ident; let mut path = path.clone(); for seg in &mut path.segments { @@ -493,24 +488,25 @@ impl<'hir> LoweringContext<'_, 'hir> { self.with_hir_id_owner(new_node_id, |this| { let res = this.lower_res(res); - let path = this.lower_path_extra(res, &path, ParamMode::Explicit, None); + let path = this.lower_path_extra(res, &path, ParamMode::Explicit); let kind = hir::ItemKind::Use(path, hir::UseKind::Single); let vis = this.rebuild_vis(&vis); if let Some(attrs) = attrs { this.attrs.insert(hir::HirId::make_owner(new_id), attrs); } - this.insert_item(hir::Item { + let item = hir::Item { def_id: new_id, ident: this.lower_ident(ident), kind, vis, span: this.lower_span(span), - }); + }; + hir::OwnerNode::Item(this.arena.alloc(item)) }); } - let path = self.lower_path_extra(ret_res, &path, ParamMode::Explicit, None); + let path = self.lower_path_extra(ret_res, &path, ParamMode::Explicit); hir::ItemKind::Use(path, hir::UseKind::Single) } UseTreeKind::Glob => { @@ -550,7 +546,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.allocate_hir_id_counter(id); + let new_hir_id = self.resolver.local_def_id(id); let mut prefix = prefix.clone(); @@ -574,13 +570,14 @@ impl<'hir> LoweringContext<'_, 'hir> { this.attrs.insert(hir::HirId::make_owner(new_hir_id), attrs); } - this.insert_item(hir::Item { + let item = hir::Item { def_id: new_hir_id, ident: this.lower_ident(ident), kind, vis, span: this.lower_span(use_tree.span), - }); + }; + hir::OwnerNode::Item(this.arena.alloc(item)) }); } @@ -610,7 +607,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let res = self.expect_full_res_from_use(id).next().unwrap_or(Res::Err); let res = self.lower_res(res); - let path = self.lower_path_extra(res, &prefix, ParamMode::Explicit, None); + let path = self.lower_path_extra(res, &prefix, ParamMode::Explicit); hir::ItemKind::Use(path, hir::UseKind::ListStem) } } @@ -647,11 +644,11 @@ impl<'hir> LoweringContext<'_, 'hir> { respan(self.lower_span(vis.span), vis_kind) } - fn lower_foreign_item(&mut self, i: &ForeignItem) -> hir::ForeignItem<'hir> { + fn lower_foreign_item(&mut self, i: &ForeignItem) -> &'hir hir::ForeignItem<'hir> { let hir_id = self.lower_node_id(i.id); let def_id = hir_id.expect_owner(); self.lower_attrs(hir_id, &i.attrs); - hir::ForeignItem { + let item = hir::ForeignItem { def_id, ident: self.lower_ident(i.ident), kind: match i.kind { @@ -679,17 +676,17 @@ impl<'hir> LoweringContext<'_, 'hir> { ForeignItemKind::TyAlias(..) => hir::ForeignItemKind::Type, ForeignItemKind::MacCall(_) => panic!("macro shouldn't exist here"), }, - vis: self.lower_visibility(&i.vis, None), + vis: self.lower_visibility(&i.vis), span: self.lower_span(i.span), - } + }; + self.arena.alloc(item) } - fn lower_foreign_item_ref(&mut self, i: &ForeignItem) -> hir::ForeignItemRef<'hir> { + fn lower_foreign_item_ref(&mut self, i: &ForeignItem) -> hir::ForeignItemRef { hir::ForeignItemRef { - id: hir::ForeignItemId { def_id: self.allocate_hir_id_counter(i.id) }, + id: hir::ForeignItemId { def_id: self.resolver.local_def_id(i.id) }, ident: self.lower_ident(i.ident), span: self.lower_span(i.span), - vis: self.lower_visibility(&i.vis, Some(i.id)), } } @@ -757,12 +754,12 @@ impl<'hir> LoweringContext<'_, 'hir> { // FIXME(jseyfried): positional field hygiene. None => Ident::new(sym::integer(index), self.lower_span(f.span)), }, - vis: self.lower_visibility(&f.vis, None), + vis: self.lower_visibility(&f.vis), ty, } } - fn lower_trait_item(&mut self, i: &AssocItem) -> hir::TraitItem<'hir> { + fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> { let hir_id = self.lower_node_id(i.id); let trait_item_def_id = hir_id.expect_owner(); @@ -805,13 +802,14 @@ impl<'hir> LoweringContext<'_, 'hir> { }; self.lower_attrs(hir_id, &i.attrs); - hir::TraitItem { + let item = hir::TraitItem { def_id: trait_item_def_id, ident: self.lower_ident(i.ident), generics, kind, span: self.lower_span(i.span), - } + }; + self.arena.alloc(item) } fn lower_trait_item_ref(&mut self, i: &AssocItem) -> hir::TraitItemRef { @@ -841,7 +839,7 @@ impl<'hir> LoweringContext<'_, 'hir> { self.expr(span, hir::ExprKind::Err, AttrVec::new()) } - fn lower_impl_item(&mut self, i: &AssocItem) -> hir::ImplItem<'hir> { + fn lower_impl_item(&mut self, i: &AssocItem) -> &'hir hir::ImplItem<'hir> { let impl_item_def_id = self.resolver.local_def_id(i.id); let (generics, kind) = match &i.kind { @@ -895,26 +893,26 @@ impl<'hir> LoweringContext<'_, 'hir> { let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value); let hir_id = self.lower_node_id(i.id); self.lower_attrs(hir_id, &i.attrs); - hir::ImplItem { + let item = hir::ImplItem { def_id: hir_id.expect_owner(), ident: self.lower_ident(i.ident), generics, - vis: self.lower_visibility(&i.vis, None), + vis: self.lower_visibility(&i.vis), defaultness, kind, span: self.lower_span(i.span), - } + }; + self.arena.alloc(item) } - fn lower_impl_item_ref(&mut self, i: &AssocItem) -> hir::ImplItemRef<'hir> { + fn lower_impl_item_ref(&mut self, i: &AssocItem) -> hir::ImplItemRef { // Since `default impl` is not yet implemented, this is always true in impls. let has_value = true; let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value); hir::ImplItemRef { - id: hir::ImplItemId { def_id: self.allocate_hir_id_counter(i.id) }, + id: hir::ImplItemId { def_id: self.resolver.local_def_id(i.id) }, ident: self.lower_ident(i.ident), span: self.lower_span(i.span), - vis: self.lower_visibility(&i.vis, Some(i.id)), defaultness, kind: match &i.kind { AssocItemKind::Const(..) => hir::AssocItemKind::Const, @@ -932,25 +930,15 @@ impl<'hir> LoweringContext<'_, 'hir> { /// lowered. This can happen during `lower_impl_item_ref()` where we need to /// lower a `Visibility` value although we haven't lowered the owning /// `ImplItem` in question yet. - fn lower_visibility( - &mut self, - v: &Visibility, - explicit_owner: Option<NodeId>, - ) -> hir::Visibility<'hir> { + fn lower_visibility(&mut self, v: &Visibility) -> hir::Visibility<'hir> { let node = match v.kind { VisibilityKind::Public => hir::VisibilityKind::Public, VisibilityKind::Crate(sugar) => hir::VisibilityKind::Crate(sugar), VisibilityKind::Restricted { ref path, id } => { debug!("lower_visibility: restricted path id = {:?}", id); - let lowered_id = if let Some(owner) = explicit_owner { - self.lower_node_id_with_owner(id, owner) - } else { - self.lower_node_id(id) - }; - let res = self.expect_full_res(id); - let res = self.lower_res(res); + let lowered_id = self.lower_node_id(id); hir::VisibilityKind::Restricted { - path: self.lower_path_extra(res, path, ParamMode::Explicit, explicit_owner), + path: self.lower_path(id, path, ParamMode::Explicit), hir_id: lowered_id, } } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 66bcd698e6a..5ec060f6540 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -80,8 +80,6 @@ mod item; mod pat; mod path; -const HIR_ID_COUNTER_LOCKED: u32 = 0xFFFFFFFF; - rustc_hir::arena_types!(rustc_arena::declare_arena, 'tcx); struct LoweringContext<'a, 'hir: 'a> { @@ -150,8 +148,8 @@ struct LoweringContext<'a, 'hir: 'a> { /// vector. in_scope_lifetimes: Vec<ParamName>, - current_hir_id_owner: (LocalDefId, u32), - item_local_id_counters: NodeMap<u32>, + current_hir_id_owner: LocalDefId, + item_local_id_counter: hir::ItemLocalId, node_id_to_hir_id: IndexVec<NodeId, Option<hir::HirId>>, allow_try_trait: Option<Lrc<[Symbol]>>, @@ -330,8 +328,8 @@ pub fn lower_crate<'a, 'hir>( is_in_trait_impl: false, is_in_dyn_type: false, anonymous_lifetime_mode: AnonymousLifetimeMode::PassThrough, - current_hir_id_owner: (CRATE_DEF_ID, 0), - item_local_id_counters: Default::default(), + current_hir_id_owner: CRATE_DEF_ID, + item_local_id_counter: hir::ItemLocalId::new(0), node_id_to_hir_id: IndexVec::new(), generator_kind: None, task_context: None, @@ -412,15 +410,15 @@ enum AnonymousLifetimeMode { impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_crate(mut self, c: &Crate) -> &'hir hir::Crate<'hir> { - self.lower_node_id(CRATE_NODE_ID); - debug_assert!(self.node_id_to_hir_id[CRATE_NODE_ID] == Some(hir::CRATE_HIR_ID)); + debug_assert_eq!(self.resolver.local_def_id(CRATE_NODE_ID), CRATE_DEF_ID); visit::walk_crate(&mut item::ItemLowerer { lctx: &mut self }, c); - let module = self.arena.alloc(self.lower_mod(&c.items, c.span)); - self.lower_attrs(hir::CRATE_HIR_ID, &c.attrs); - self.owners.ensure_contains_elem(CRATE_DEF_ID, || None); - self.owners[CRATE_DEF_ID] = Some(hir::OwnerNode::Crate(module)); + self.with_hir_id_owner(CRATE_NODE_ID, |lctx| { + let module = lctx.lower_mod(&c.items, c.span); + lctx.lower_attrs(hir::CRATE_HIR_ID, &c.attrs); + hir::OwnerNode::Crate(lctx.arena.alloc(module)) + }); let mut trait_map: FxHashMap<_, FxHashMap<_, _>> = FxHashMap::default(); for (k, v) in self.resolver.take_trait_map().into_iter() { @@ -456,47 +454,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.arena.alloc(krate) } - fn insert_item(&mut self, item: hir::Item<'hir>) -> hir::ItemId { - let id = item.item_id(); - 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)); - id - } - - fn insert_foreign_item(&mut self, item: hir::ForeignItem<'hir>) -> hir::ForeignItemId { - let id = item.foreign_item_id(); - 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)); - id - } - - fn insert_impl_item(&mut self, item: hir::ImplItem<'hir>) -> hir::ImplItemId { - let id = item.impl_item_id(); - 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)); - id - } - - fn insert_trait_item(&mut self, item: hir::TraitItem<'hir>) -> hir::TraitItemId { - let id = item.trait_item_id(); - 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)); - id - } - - 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.owner - } - fn create_stable_hashing_context(&self) -> LoweringHasher<'_> { LoweringHasher { source_map: CachingSourceMapView::new(self.sess.source_map()), @@ -504,47 +461,33 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } - fn lower_node_id_generic( + fn with_hir_id_owner( &mut self, - ast_node_id: NodeId, - alloc_hir_id: impl FnOnce(&mut Self) -> hir::HirId, - ) -> hir::HirId { - assert_ne!(ast_node_id, DUMMY_NODE_ID); - - let min_size = ast_node_id.as_usize() + 1; + owner: NodeId, + f: impl FnOnce(&mut Self) -> hir::OwnerNode<'hir>, + ) -> LocalDefId { + let def_id = self.resolver.local_def_id(owner); - if min_size > self.node_id_to_hir_id.len() { - self.node_id_to_hir_id.resize(min_size, None); + // Always allocate the first `HirId` for the owner itself. + self.node_id_to_hir_id.ensure_contains_elem(owner, || None); + if let Some(_lowered) = self.node_id_to_hir_id[owner] { + panic!("with_hir_id_owner must not be called multiple times on owner {:?}", def_id); } + self.node_id_to_hir_id[owner] = Some(hir::HirId::make_owner(def_id)); - if let Some(existing_hir_id) = self.node_id_to_hir_id[ast_node_id] { - existing_hir_id - } else { - // Generate a new `HirId`. - let hir_id = alloc_hir_id(self); - self.node_id_to_hir_id[ast_node_id] = Some(hir_id); + let current_owner = std::mem::replace(&mut self.current_hir_id_owner, def_id); + let current_local_counter = + std::mem::replace(&mut self.item_local_id_counter, hir::ItemLocalId::new(1)); - hir_id - } - } + let item = f(self); - fn with_hir_id_owner<T>(&mut self, owner: NodeId, f: impl FnOnce(&mut Self) -> T) -> T { - let counter = self - .item_local_id_counters - .insert(owner, HIR_ID_COUNTER_LOCKED) - .unwrap_or_else(|| panic!("no `item_local_id_counters` entry for {:?}", owner)); - let def_id = self.resolver.local_def_id(owner); - let old_owner = std::mem::replace(&mut self.current_hir_id_owner, (def_id, counter)); - let ret = f(self); - let (new_def_id, new_counter) = - std::mem::replace(&mut self.current_hir_id_owner, old_owner); + self.current_hir_id_owner = current_owner; + self.item_local_id_counter = current_local_counter; - debug_assert!(def_id == new_def_id); - debug_assert!(new_counter >= counter); + self.owners.ensure_contains_elem(def_id, || None); + self.owners[def_id] = Some(item); - let prev = self.item_local_id_counters.insert(owner, new_counter).unwrap(); - debug_assert!(prev == HIR_ID_COUNTER_LOCKED); - ret + def_id } /// This method allocates a new `HirId` for the given `NodeId` and stores it in @@ -554,35 +497,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { /// `HirIdValidator` later on, which makes sure that all `NodeId`s got mapped /// properly. Calling the method twice with the same `NodeId` is fine though. fn lower_node_id(&mut self, ast_node_id: NodeId) -> hir::HirId { - self.lower_node_id_generic(ast_node_id, |this| { - let &mut (owner, ref mut local_id_counter) = &mut this.current_hir_id_owner; - let local_id = *local_id_counter; - *local_id_counter += 1; - hir::HirId { owner, local_id: hir::ItemLocalId::from_u32(local_id) } - }) - } - - fn lower_node_id_with_owner(&mut self, ast_node_id: NodeId, owner: NodeId) -> hir::HirId { - self.lower_node_id_generic(ast_node_id, |this| { - let local_id_counter = this - .item_local_id_counters - .get_mut(&owner) - .expect("called `lower_node_id_with_owner` before `allocate_hir_id_counter`"); - let local_id = *local_id_counter; - - // We want to be sure not to modify the counter in the map while it - // is also on the stack. Otherwise we'll get lost updates when writing - // back from the stack to the map. - debug_assert!(local_id != HIR_ID_COUNTER_LOCKED); - - *local_id_counter += 1; - let owner = this.resolver.opt_local_def_id(owner).expect( - "you forgot to call `create_def` or are lowering node-IDs \ - that do not belong to the current owner", - ); + assert_ne!(ast_node_id, DUMMY_NODE_ID); - hir::HirId { owner, local_id: hir::ItemLocalId::from_u32(local_id) } - }) + self.node_id_to_hir_id.ensure_contains_elem(ast_node_id, || None); + if let Some(existing_hir_id) = self.node_id_to_hir_id[ast_node_id] { + existing_hir_id + } else { + // Generate a new `HirId`. + let owner = self.current_hir_id_owner; + let local_id = self.item_local_id_counter; + self.item_local_id_counter.increment_by(1); + let hir_id = hir::HirId { owner, local_id }; + self.node_id_to_hir_id[ast_node_id] = Some(hir_id); + hir_id + } } fn next_id(&mut self) -> hir::HirId { @@ -592,7 +520,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_res(&mut self, res: Res<NodeId>) -> Res { res.map_id(|id| { - self.lower_node_id_generic(id, |_| { + self.node_id_to_hir_id.get(id).copied().flatten().unwrap_or_else(|| { panic!("expected `NodeId` to be lowered already for res {:#?}", res); }) }) @@ -655,7 +583,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { /// Mark a span as relative to the current owning item. fn lower_span(&self, span: Span) -> Span { if self.sess.opts.debugging_opts.incremental_relative_spans { - span.with_parent(Some(self.current_hir_id_owner.0)) + span.with_parent(Some(self.current_hir_id_owner)) } else { // Do not make spans relative when not using incremental compilation. span @@ -828,7 +756,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // wouldn't have been added yet. let generics = this.lower_generics_mut( generics, - ImplTraitContext::Universal(&mut params, this.current_hir_id_owner.0), + ImplTraitContext::Universal(&mut params, this.current_hir_id_owner), ); let res = f(this, &mut params); (params, (generics, res)) @@ -1034,7 +962,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } AssocTyConstraintKind::Bound { ref bounds } => { let mut capturable_lifetimes; - let mut parent_def_id = self.current_hir_id_owner.0; + let mut parent_def_id = self.current_hir_id_owner; // Piggy-back on the `impl Trait` context to figure out the correct behavior. let (desugar_to_impl_trait, itctx) = match itctx { // We are in the return position: @@ -1162,7 +1090,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Construct an AnonConst where the expr is the "ty"'s path. - let parent_def_id = self.current_hir_id_owner.0; + let parent_def_id = self.current_hir_id_owner; let node_id = self.resolver.next_node_id(); // Add a definition for the in-band const def. @@ -1428,12 +1356,13 @@ 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.allocate_hir_id_counter(opaque_ty_node_id); + let opaque_ty_def_id = self.resolver.local_def_id(opaque_ty_node_id); - let collected_lifetimes = self.with_hir_id_owner(opaque_ty_node_id, move |lctx| { + let mut collected_lifetimes = Vec::new(); + self.with_hir_id_owner(opaque_ty_node_id, |lctx| { let hir_bounds = lower_bounds(lctx); - let collected_lifetimes = lifetimes_from_impl_trait_bounds( + collected_lifetimes = lifetimes_from_impl_trait_bounds( opaque_ty_node_id, &hir_bounds, capturable_lifetimes, @@ -1486,9 +1415,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }; trace!("lower_opaque_impl_trait: {:#?}", opaque_ty_def_id); - lctx.generate_opaque_type(opaque_ty_def_id, opaque_ty_item, span, opaque_ty_span); - - collected_lifetimes + lctx.generate_opaque_type(opaque_ty_def_id, opaque_ty_item, span, opaque_ty_span) }); let lifetimes = @@ -1510,7 +1437,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { opaque_ty_item: hir::OpaqueTy<'hir>, span: Span, opaque_ty_span: Span, - ) { + ) -> hir::OwnerNode<'hir> { let opaque_ty_item_kind = hir::ItemKind::OpaqueTy(opaque_ty_item); // Generate an `type Foo = impl Trait;` declaration. trace!("registering opaque type with id {:#?}", opaque_ty_id); @@ -1521,11 +1448,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { vis: respan(self.lower_span(span.shrink_to_lo()), hir::VisibilityKind::Inherited), span: self.lower_span(opaque_ty_span), }; - - // Insert the item into the global item list. This usually happens - // automatically for all AST items. But this opaque type item - // does not actually exist in the AST. - self.insert_item(opaque_ty_item); + hir::OwnerNode::Item(self.arena.alloc(opaque_ty_item)) } fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> &'hir [Ident] { @@ -1594,7 +1517,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { if let Some((_, ibty)) = &mut in_band_ty_params { this.lower_ty_direct( ¶m.ty, - ImplTraitContext::Universal(ibty, this.current_hir_id_owner.0), + ImplTraitContext::Universal(ibty, this.current_hir_id_owner), ) } else { this.lower_ty_direct(¶m.ty, ImplTraitContext::disallowed()) @@ -1685,7 +1608,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.allocate_hir_id_counter(opaque_ty_node_id); + let opaque_ty_def_id = self.resolver.local_def_id(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 @@ -1735,7 +1658,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // grow. let input_lifetimes_count = self.in_scope_lifetimes.len() + self.lifetimes_to_define.len(); - let lifetime_params = self.with_hir_id_owner(opaque_ty_node_id, |this| { + let mut lifetime_params = Vec::new(); + self.with_hir_id_owner(opaque_ty_node_id, |this| { // We have to be careful to get elision right here. The // idea is that we create a lifetime parameter for each // lifetime in the return type. So, given a return type @@ -1757,7 +1681,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // // Note: this must be done after lowering the output type, // as the output type may introduce new in-band lifetimes. - let lifetime_params: Vec<(Span, ParamName)> = this + lifetime_params = this .in_scope_lifetimes .iter() .cloned() @@ -1786,9 +1710,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }; trace!("exist ty from async fn def id: {:#?}", opaque_ty_def_id); - this.generate_opaque_type(opaque_ty_def_id, opaque_ty_item, span, opaque_ty_span); - - lifetime_params + this.generate_opaque_type(opaque_ty_def_id, opaque_ty_item, span, opaque_ty_span) }); // As documented above on the variable diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index 90a22b5c209..929f427484d 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -99,7 +99,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { num_lifetimes, parenthesized_generic_args, itctx.reborrow(), - None, ) }, )), @@ -147,7 +146,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { 0, ParenthesizedGenericArgs::Err, itctx.reborrow(), - None, )); let qpath = hir::QPath::TypeRelative(ty, hir_segment); @@ -178,7 +176,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { res: Res, p: &Path, param_mode: ParamMode, - explicit_owner: Option<NodeId>, ) -> &'hir hir::Path<'hir> { self.arena.alloc(hir::Path { res, @@ -190,7 +187,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { 0, ParenthesizedGenericArgs::Err, ImplTraitContext::disallowed(), - explicit_owner, ) })), span: self.lower_span(p.span), @@ -205,7 +201,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ) -> &'hir hir::Path<'hir> { let res = self.expect_full_res(id); let res = self.lower_res(res); - self.lower_path_extra(res, p, param_mode, None) + self.lower_path_extra(res, p, param_mode) } crate fn lower_path_segment( @@ -216,7 +212,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { expected_lifetimes: usize, parenthesized_generic_args: ParenthesizedGenericArgs, itctx: ImplTraitContext<'_, 'hir>, - explicit_owner: Option<NodeId>, ) -> hir::PathSegment<'hir> { debug!( "path_span: {:?}, lower_path_segment(segment: {:?}, expected_lifetimes: {:?})", @@ -354,11 +349,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } let res = self.expect_full_res(segment.id); - let id = if let Some(owner) = explicit_owner { - self.lower_node_id_with_owner(segment.id, owner) - } else { - self.lower_node_id(segment.id) - }; + let id = self.lower_node_id(segment.id); debug!( "lower_path_segment: ident={:?} original-id={:?} new-id={:?}", segment.ident, segment.id, id, diff --git a/compiler/rustc_ast_passes/Cargo.toml b/compiler/rustc_ast_passes/Cargo.toml index 4a6eb80fb30..9312a68bc60 100644 --- a/compiler/rustc_ast_passes/Cargo.toml +++ b/compiler/rustc_ast_passes/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_ast_passes" version = "0.0.0" -edition = "2018" +edition = "2021" [dependencies] itertools = "0.9" diff --git a/compiler/rustc_ast_pretty/Cargo.toml b/compiler/rustc_ast_pretty/Cargo.toml index fa88740103b..29f2be4cf46 100644 --- a/compiler/rustc_ast_pretty/Cargo.toml +++ b/compiler/rustc_ast_pretty/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_ast_pretty" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] doctest = false diff --git a/compiler/rustc_attr/Cargo.toml b/compiler/rustc_attr/Cargo.toml index 0566379e1f5..ba310a6860e 100644 --- a/compiler/rustc_attr/Cargo.toml +++ b/compiler/rustc_attr/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_attr" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] doctest = false diff --git a/compiler/rustc_borrowck/Cargo.toml b/compiler/rustc_borrowck/Cargo.toml index c683c388ba9..75e9c69af4e 100644 --- a/compiler/rustc_borrowck/Cargo.toml +++ b/compiler/rustc_borrowck/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_borrowck" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] doctest = false diff --git a/compiler/rustc_builtin_macros/Cargo.toml b/compiler/rustc_builtin_macros/Cargo.toml index 2370ac201b0..fd34f947f72 100644 --- a/compiler/rustc_builtin_macros/Cargo.toml +++ b/compiler/rustc_builtin_macros/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_builtin_macros" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] doctest = false diff --git a/compiler/rustc_codegen_cranelift/Cargo.toml b/compiler/rustc_codegen_cranelift/Cargo.toml index 6f40fc0fcb8..61d40702a32 100644 --- a/compiler/rustc_codegen_cranelift/Cargo.toml +++ b/compiler/rustc_codegen_cranelift/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_codegen_cranelift" version = "0.1.0" -edition = "2018" +edition = "2021" [lib] crate-type = ["dylib"] diff --git a/compiler/rustc_codegen_cranelift/src/bin/cg_clif_build_sysroot.rs b/compiler/rustc_codegen_cranelift/src/bin/cg_clif_build_sysroot.rs index e7cd5edbbf6..89e0cb8d90e 100644 --- a/compiler/rustc_codegen_cranelift/src/bin/cg_clif_build_sysroot.rs +++ b/compiler/rustc_codegen_cranelift/src/bin/cg_clif_build_sysroot.rs @@ -8,7 +8,6 @@ #![feature(rustc_private)] -extern crate rustc_data_structures; extern crate rustc_driver; extern crate rustc_interface; extern crate rustc_session; diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml index 3c99febbd57..3f024434581 100644 --- a/compiler/rustc_codegen_llvm/Cargo.toml +++ b/compiler/rustc_codegen_llvm/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_codegen_llvm" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] test = false diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index 56b93f83466..51c70f0868f 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -305,9 +305,12 @@ pub fn from_fn_attrs(cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value, instance: ty:: let mut function_features = codegen_fn_attrs .target_features .iter() - .map(|f| { + .flat_map(|f| { let feature = &f.as_str(); - format!("+{}", llvm_util::to_llvm_feature(cx.tcx.sess, feature)) + llvm_util::to_llvm_feature(cx.tcx.sess, feature) + .into_iter() + .map(|f| format!("+{}", f)) + .collect::<Vec<String>>() }) .chain(codegen_fn_attrs.instruction_set.iter().map(|x| match x { InstructionSetAttr::ArmA32 => "-thumb-mode".to_string(), diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs index f612785e5a4..99b30264d09 100644 --- a/compiler/rustc_codegen_llvm/src/back/lto.rs +++ b/compiler/rustc_codegen_llvm/src/back/lto.rs @@ -325,6 +325,20 @@ fn fat_lto( drop(linker); save_temp_bitcode(&cgcx, &module, "lto.input"); + // Fat LTO also suffers from the invalid DWARF issue similar to Thin LTO. + // Here we rewrite all `DICompileUnit` pointers if there is only one `DICompileUnit`. + // This only works around the problem when codegen-units = 1. + // Refer to the comments in the `optimize_thin_module` function for more details. + let mut cu1 = ptr::null_mut(); + let mut cu2 = ptr::null_mut(); + unsafe { llvm::LLVMRustLTOGetDICompileUnit(llmod, &mut cu1, &mut cu2) }; + if !cu2.is_null() { + let _timer = + cgcx.prof.generic_activity_with_arg("LLVM_fat_lto_patch_debuginfo", &*module.name); + unsafe { llvm::LLVMRustLTOPatchDICompileUnit(llmod, cu1) }; + save_temp_bitcode(cgcx, &module, "fat-lto-after-patch"); + } + // Internalize everything below threshold to help strip out more modules and such. unsafe { let ptr = symbols_below_threshold.as_ptr(); @@ -748,7 +762,7 @@ pub unsafe fn optimize_thin_module( // an error. let mut cu1 = ptr::null_mut(); let mut cu2 = ptr::null_mut(); - llvm::LLVMRustThinLTOGetDICompileUnit(llmod, &mut cu1, &mut cu2); + llvm::LLVMRustLTOGetDICompileUnit(llmod, &mut cu1, &mut cu2); if !cu2.is_null() { let msg = "multiple source DICompileUnits found"; return Err(write::llvm_err(&diag_handler, msg)); @@ -847,7 +861,7 @@ pub unsafe fn optimize_thin_module( let _timer = cgcx .prof .generic_activity_with_arg("LLVM_thin_lto_patch_debuginfo", thin_module.name()); - llvm::LLVMRustThinLTOPatchDICompileUnit(llmod, cu1); + llvm::LLVMRustLTOPatchDICompileUnit(llmod, cu1); save_temp_bitcode(cgcx, &module, "thin-lto-after-patch"); } diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 3f2ed02d90d..d8c2a345fb0 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -2377,12 +2377,8 @@ extern "C" { len: usize, out_len: &mut usize, ) -> *const u8; - pub fn LLVMRustThinLTOGetDICompileUnit( - M: &Module, - CU1: &mut *mut c_void, - CU2: &mut *mut c_void, - ); - pub fn LLVMRustThinLTOPatchDICompileUnit(M: &Module, CU: *mut c_void); + pub fn LLVMRustLTOGetDICompileUnit(M: &Module, CU1: &mut *mut c_void, CU2: &mut *mut c_void); + pub fn LLVMRustLTOPatchDICompileUnit(M: &Module, CU: *mut c_void); pub fn LLVMRustLinkerNew(M: &'a Module) -> &'a mut Linker<'a>; pub fn LLVMRustLinkerAdd( diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 3b64ec1a991..f9172e43773 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -166,25 +166,32 @@ pub fn time_trace_profiler_finish(file_name: &str) { // Though note that Rust can also be build with an external precompiled version of LLVM // which might lead to failures if the oldest tested / supported LLVM version // doesn't yet support the relevant intrinsics -pub fn to_llvm_feature<'a>(sess: &Session, s: &'a str) -> &'a str { +pub fn to_llvm_feature<'a>(sess: &Session, s: &'a str) -> Vec<&'a str> { let arch = if sess.target.arch == "x86_64" { "x86" } else { &*sess.target.arch }; match (arch, s) { - ("x86", "pclmulqdq") => "pclmul", - ("x86", "rdrand") => "rdrnd", - ("x86", "bmi1") => "bmi", - ("x86", "cmpxchg16b") => "cx16", - ("x86", "avx512vaes") => "vaes", - ("x86", "avx512gfni") => "gfni", - ("x86", "avx512vpclmulqdq") => "vpclmulqdq", - ("aarch64", "fp") => "fp-armv8", - ("aarch64", "fp16") => "fullfp16", - ("aarch64", "fhm") => "fp16fml", - ("aarch64", "rcpc2") => "rcpc-immo", - ("aarch64", "dpb") => "ccpp", - ("aarch64", "dpb2") => "ccdp", - ("aarch64", "frintts") => "fptoint", - ("aarch64", "fcma") => "complxnum", - (_, s) => s, + ("x86", "sse4.2") => { + if get_version() >= (14, 0, 0) { + vec!["sse4.2", "crc32"] + } else { + vec!["sse4.2"] + } + } + ("x86", "pclmulqdq") => vec!["pclmul"], + ("x86", "rdrand") => vec!["rdrnd"], + ("x86", "bmi1") => vec!["bmi"], + ("x86", "cmpxchg16b") => vec!["cx16"], + ("x86", "avx512vaes") => vec!["vaes"], + ("x86", "avx512gfni") => vec!["gfni"], + ("x86", "avx512vpclmulqdq") => vec!["vpclmulqdq"], + ("aarch64", "fp") => vec!["fp-armv8"], + ("aarch64", "fp16") => vec!["fullfp16"], + ("aarch64", "fhm") => vec!["fp16fml"], + ("aarch64", "rcpc2") => vec!["rcpc-immo"], + ("aarch64", "dpb") => vec!["ccpp"], + ("aarch64", "dpb2") => vec!["ccdp"], + ("aarch64", "frintts") => vec!["fptoint"], + ("aarch64", "fcma") => vec!["complxnum"], + (_, s) => vec![s], } } @@ -198,9 +205,13 @@ pub fn target_features(sess: &Session) -> Vec<Symbol> { }, ) .filter(|feature| { - let llvm_feature = to_llvm_feature(sess, feature); - let cstr = CString::new(llvm_feature).unwrap(); - unsafe { llvm::LLVMRustHasFeature(target_machine, cstr.as_ptr()) } + for llvm_feature in to_llvm_feature(sess, feature) { + let cstr = CString::new(llvm_feature).unwrap(); + if unsafe { llvm::LLVMRustHasFeature(target_machine, cstr.as_ptr()) } { + return true; + } + } + false }) .map(|feature| Symbol::intern(feature)) .collect() @@ -253,12 +264,19 @@ fn print_target_features(sess: &Session, tm: &llvm::TargetMachine) { let mut rustc_target_features = supported_target_features(sess) .iter() .filter_map(|(feature, _gate)| { - let llvm_feature = to_llvm_feature(sess, *feature); - // LLVM asserts that these are sorted. LLVM and Rust both use byte comparison for these strings. - target_features.binary_search_by_key(&llvm_feature, |(f, _d)| *f).ok().map(|index| { - let (_f, desc) = target_features.remove(index); - (*feature, desc) - }) + for llvm_feature in to_llvm_feature(sess, *feature) { + // LLVM asserts that these are sorted. LLVM and Rust both use byte comparison for these strings. + match target_features.binary_search_by_key(&llvm_feature, |(f, _d)| (*f)).ok().map( + |index| { + let (_f, desc) = target_features.remove(index); + (*feature, desc) + }, + ) { + Some(v) => return Some(v), + None => {} + } + } + None }) .collect::<Vec<_>>(); rustc_target_features.extend_from_slice(&[( @@ -373,30 +391,30 @@ pub fn llvm_global_features(sess: &Session) -> Vec<String> { let filter = |s: &str| { if s.is_empty() { - return None; + return vec![]; } let feature = if s.starts_with('+') || s.starts_with('-') { &s[1..] } else { - return Some(s.to_string()); + return vec![s.to_string()]; }; // Rustc-specific feature requests like `+crt-static` or `-crt-static` // are not passed down to LLVM. if RUSTC_SPECIFIC_FEATURES.contains(&feature) { - return None; + return vec![]; } // ... otherwise though we run through `to_llvm_feature` feature when // passing requests down to LLVM. This means that all in-language // features also work on the command line instead of having two // different names when the LLVM name and the Rust name differ. - Some(format!("{}{}", &s[..1], to_llvm_feature(sess, feature))) + to_llvm_feature(sess, feature).iter().map(|f| format!("{}{}", &s[..1], f)).collect() }; // Features implied by an implicit or explicit `--target`. - features.extend(sess.target.features.split(',').filter_map(&filter)); + features.extend(sess.target.features.split(',').flat_map(&filter)); // -Ctarget-features - features.extend(sess.opts.cg.target_feature.split(',').filter_map(&filter)); + features.extend(sess.opts.cg.target_feature.split(',').flat_map(&filter)); features } diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml index 1446624b881..0713e167c53 100644 --- a/compiler/rustc_codegen_ssa/Cargo.toml +++ b/compiler/rustc_codegen_ssa/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_codegen_ssa" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] test = false diff --git a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs index c139f915e6c..c710fcc2c1d 100644 --- a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs +++ b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs @@ -3,9 +3,11 @@ use rustc_index::vec::IndexVec; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir; use rustc_middle::ty; +use rustc_middle::ty::layout::LayoutOf; use rustc_session::config::DebugInfo; use rustc_span::symbol::{kw, Symbol}; use rustc_span::{BytePos, Span}; +use rustc_target::abi::Abi; use rustc_target::abi::Size; use super::operand::{OperandRef, OperandValue}; @@ -368,21 +370,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { { let arg_index = place.local.index() - 1; if target_is_msvc { - // Rust compiler decomposes every &str or slice argument into two components: - // a pointer to the memory address where the data is stored and a usize representing - // the length of the str (or slice). These components will later be used to reconstruct - // the original argument inside the body of the function that owns it (see the - // definition of debug_introduce_local for more details). - // - // Since the original argument is declared inside a function rather than being passed - // in as an argument, it must be marked as a LocalVariable for MSVC debuggers to visualize - // its data correctly. (See issue #81894 for an in-depth description of the problem). - match *var_ty.kind() { - ty::Ref(_, inner_type, _) => match *inner_type.kind() { - ty::Slice(_) | ty::Str => VariableKind::LocalVariable, - _ => VariableKind::ArgumentVariable(arg_index + 1), - }, - _ => VariableKind::ArgumentVariable(arg_index + 1), + // ScalarPair parameters are spilled to the stack so they need to + // be marked as a `LocalVariable` for MSVC debuggers to visualize + // their data correctly. (See #81894 & #88625) + let var_ty_layout = self.cx.layout_of(var_ty); + if let Abi::ScalarPair(_, _) = var_ty_layout.abi { + VariableKind::LocalVariable + } else { + VariableKind::ArgumentVariable(arg_index + 1) } } else { // FIXME(eddyb) shouldn't `ArgumentVariable` indices be diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index 8e3982c72d7..37f5de309ba 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -129,6 +129,7 @@ impl<'a, 'tcx, V: CodegenObject> LocalRef<'tcx, V> { /////////////////////////////////////////////////////////////////////////// +#[instrument(level = "debug", skip(cx))] pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( cx: &'a Bx::CodegenCx, instance: Instance<'tcx>, diff --git a/compiler/rustc_const_eval/Cargo.toml b/compiler/rustc_const_eval/Cargo.toml index 1653d5cf6c5..a51273732ae 100644 --- a/compiler/rustc_const_eval/Cargo.toml +++ b/compiler/rustc_const_eval/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_const_eval" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] doctest = false diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index a6375ad0e02..fc69770bf6a 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -77,7 +77,7 @@ macro_rules! throw_validation_failure { /// macro_rules! try_validation { ($e:expr, $where:expr, - $( $( $p:pat )|+ => { $( $what_fmt:expr ),+ } $( expected { $( $expected_fmt:expr ),+ } )? ),+ $(,)? + $( $( $p:pat_param )|+ => { $( $what_fmt:expr ),+ } $( expected { $( $expected_fmt:expr ),+ } )? ),+ $(,)? ) => {{ match $e { Ok(x) => x, diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml index bc13ca26e2e..49962570129 100644 --- a/compiler/rustc_data_structures/Cargo.toml +++ b/compiler/rustc_data_structures/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_data_structures" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] doctest = false diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index dd6a17b92ae..b1f04bfbf0a 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -18,7 +18,6 @@ #![feature(extend_one)] #![feature(hash_raw_entry)] #![feature(in_band_lifetimes)] -#![feature(iter_map_while)] #![feature(maybe_uninit_uninit_array)] #![feature(min_specialization)] #![feature(never_type)] diff --git a/compiler/rustc_data_structures/src/sharded.rs b/compiler/rustc_data_structures/src/sharded.rs index 14db71cb8f0..417c61242a5 100644 --- a/compiler/rustc_data_structures/src/sharded.rs +++ b/compiler/rustc_data_structures/src/sharded.rs @@ -1,6 +1,5 @@ use crate::fx::{FxHashMap, FxHasher}; use crate::sync::{Lock, LockGuard}; -use smallvec::SmallVec; use std::borrow::Borrow; use std::collections::hash_map::RawEntryMut; use std::hash::{Hash, Hasher}; @@ -37,24 +36,7 @@ impl<T: Default> Default for Sharded<T> { impl<T> Sharded<T> { #[inline] pub fn new(mut value: impl FnMut() -> T) -> Self { - // Create a vector of the values we want - let mut values: SmallVec<[_; SHARDS]> = - (0..SHARDS).map(|_| CacheAligned(Lock::new(value()))).collect(); - - // Create an uninitialized array - let mut shards: mem::MaybeUninit<[CacheAligned<Lock<T>>; SHARDS]> = - mem::MaybeUninit::uninit(); - - unsafe { - // Copy the values into our array - let first = shards.as_mut_ptr() as *mut CacheAligned<Lock<T>>; - values.as_ptr().copy_to_nonoverlapping(first, SHARDS); - - // Ignore the content of the vector - values.set_len(0); - - Sharded { shards: shards.assume_init() } - } + Sharded { shards: [(); SHARDS].map(|()| CacheAligned(Lock::new(value()))) } } /// The shard is selected by hashing `val` with `FxHasher`. diff --git a/compiler/rustc_driver/Cargo.toml b/compiler/rustc_driver/Cargo.toml index ba8616cc6ef..6721e00027d 100644 --- a/compiler/rustc_driver/Cargo.toml +++ b/compiler/rustc_driver/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_driver" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] crate-type = ["dylib"] diff --git a/compiler/rustc_error_codes/Cargo.toml b/compiler/rustc_error_codes/Cargo.toml index 270e5301895..7d5f3e4672a 100644 --- a/compiler/rustc_error_codes/Cargo.toml +++ b/compiler/rustc_error_codes/Cargo.toml @@ -1,4 +1,4 @@ [package] name = "rustc_error_codes" version = "0.0.0" -edition = "2018" +edition = "2021" diff --git a/compiler/rustc_errors/Cargo.toml b/compiler/rustc_errors/Cargo.toml index c74fd60e530..4846dc43605 100644 --- a/compiler/rustc_errors/Cargo.toml +++ b/compiler/rustc_errors/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_errors" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] doctest = false diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index b1526cf78d2..60a48b5a2d9 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -13,9 +13,11 @@ #[macro_use] extern crate rustc_macros; +#[macro_use] +extern crate tracing; + pub use emitter::ColorConfig; -use tracing::debug; use Level::*; use emitter::{is_case_difference, Emitter, EmitterWriter}; @@ -1028,15 +1030,13 @@ impl HandlerInner { let mut error_codes = self .emitted_diagnostic_codes .iter() - .filter_map(|x| { - match &x { + .filter_map(|x| match &x { DiagnosticId::Error(s) - if let Ok(Some(_explanation)) = registry.try_find_description(s) => + if registry.try_find_description(s).map_or(false, |o| o.is_some()) => { Some(s.clone()) } _ => None, - } }) .collect::<Vec<_>>(); if !error_codes.is_empty() { diff --git a/compiler/rustc_expand/Cargo.toml b/compiler/rustc_expand/Cargo.toml index 1be9321e4fe..45237ab2e9f 100644 --- a/compiler/rustc_expand/Cargo.toml +++ b/compiler/rustc_expand/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_expand" version = "0.0.0" -edition = "2018" +edition = "2021" build = false [lib] diff --git a/compiler/rustc_feature/Cargo.toml b/compiler/rustc_feature/Cargo.toml index ee381e34251..3d8d0db20d1 100644 --- a/compiler/rustc_feature/Cargo.toml +++ b/compiler/rustc_feature/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_feature" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] doctest = false diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index efa93c18636..2baf70197dc 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -675,6 +675,10 @@ declare_features! ( /// Allows `let...else` statements. (active, let_else, "1.56.0", Some(87335), None), + /// Allows the `#[must_not_suspend]` attribute. + (active, must_not_suspend, "1.57.0", Some(83310), None), + + // ------------------------------------------------------------------------- // feature-group-end: actual feature gates // ------------------------------------------------------------------------- diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index f74ea0e0c4d..f3eaf2645f5 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -202,6 +202,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ungated!(forbid, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#)), ungated!(deny, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#)), ungated!(must_use, Normal, template!(Word, NameValueStr: "reason")), + gated!( + must_not_suspend, Normal, template!(Word, NameValueStr: "reason"), must_not_suspend, + experimental!(must_not_suspend) + ), // FIXME(#14407) ungated!( deprecated, Normal, diff --git a/compiler/rustc_fs_util/Cargo.toml b/compiler/rustc_fs_util/Cargo.toml index c417e978b31..34c3fe2a005 100644 --- a/compiler/rustc_fs_util/Cargo.toml +++ b/compiler/rustc_fs_util/Cargo.toml @@ -1,4 +1,4 @@ [package] name = "rustc_fs_util" version = "0.0.0" -edition = "2018" +edition = "2021" diff --git a/compiler/rustc_graphviz/Cargo.toml b/compiler/rustc_graphviz/Cargo.toml index 87c41ae171e..d657fdb1a77 100644 --- a/compiler/rustc_graphviz/Cargo.toml +++ b/compiler/rustc_graphviz/Cargo.toml @@ -1,4 +1,4 @@ [package] name = "rustc_graphviz" version = "0.0.0" -edition = "2018" +edition = "2021" diff --git a/compiler/rustc_hir/Cargo.toml b/compiler/rustc_hir/Cargo.toml index ff6758e66df..3b6e6db72d1 100644 --- a/compiler/rustc_hir/Cargo.toml +++ b/compiler/rustc_hir/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_hir" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] doctest = false @@ -17,4 +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"] } +odht = { version = "0.3.0", features = ["nightly"] } diff --git a/compiler/rustc_hir/src/arena.rs b/compiler/rustc_hir/src/arena.rs index 3e8b98e9f54..f07e52e04da 100644 --- a/compiler/rustc_hir/src/arena.rs +++ b/compiler/rustc_hir/src/arena.rs @@ -28,9 +28,9 @@ macro_rules! arena_types { [] pat_field: rustc_hir::PatField<$tcx>, [] fn_decl: rustc_hir::FnDecl<$tcx>, [] foreign_item: rustc_hir::ForeignItem<$tcx>, - [few] foreign_item_ref: rustc_hir::ForeignItemRef<$tcx>, + [few] foreign_item_ref: rustc_hir::ForeignItemRef, [] impl_item: rustc_hir::ImplItem<$tcx>, - [] impl_item_ref: rustc_hir::ImplItemRef<$tcx>, + [] impl_item_ref: rustc_hir::ImplItemRef, [] item: rustc_hir::Item<$tcx>, [few] inline_asm: rustc_hir::InlineAsm<$tcx>, [few] llvm_inline_asm: rustc_hir::LlvmInlineAsm<$tcx>, diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index f5fc693ce25..05b652fd5af 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2745,7 +2745,7 @@ pub enum ItemKind<'hir> { /// A module. Mod(Mod<'hir>), /// An external module, e.g. `extern { .. }`. - ForeignMod { abi: Abi, items: &'hir [ForeignItemRef<'hir>] }, + ForeignMod { abi: Abi, items: &'hir [ForeignItemRef] }, /// Module-level inline assembly (from `global_asm!`). GlobalAsm(&'hir InlineAsm<'hir>), /// A type alias, e.g., `type Foo = Bar<u8>`. @@ -2782,7 +2782,7 @@ pub struct Impl<'hir> { pub of_trait: Option<TraitRef<'hir>>, pub self_ty: &'hir Ty<'hir>, - pub items: &'hir [ImplItemRef<'hir>], + pub items: &'hir [ImplItemRef], } impl ItemKind<'_> { @@ -2846,13 +2846,12 @@ pub struct TraitItemRef { /// passes to find the impl they want without loading the ID (which /// means fewer edges in the incremental compilation graph). #[derive(Debug, HashStable_Generic)] -pub struct ImplItemRef<'hir> { +pub struct ImplItemRef { pub id: ImplItemId, #[stable_hasher(project(name))] pub ident: Ident, pub kind: AssocItemKind, pub span: Span, - pub vis: Visibility<'hir>, pub defaultness: Defaultness, } @@ -2886,12 +2885,11 @@ impl ForeignItemId { /// passes to find the impl they want without loading the ID (which /// means fewer edges in the incremental compilation graph). #[derive(Debug, HashStable_Generic)] -pub struct ForeignItemRef<'hir> { +pub struct ForeignItemRef { pub id: ForeignItemId, #[stable_hasher(project(name))] pub ident: Ident, pub span: Span, - pub vis: Visibility<'hir>, } #[derive(Debug)] diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 137782a6dc7..1ac2625dd47 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -392,10 +392,10 @@ pub trait Visitor<'v>: Sized { fn visit_impl_item(&mut self, ii: &'v ImplItem<'v>) { walk_impl_item(self, ii) } - fn visit_foreign_item_ref(&mut self, ii: &'v ForeignItemRef<'v>) { + fn visit_foreign_item_ref(&mut self, ii: &'v ForeignItemRef) { walk_foreign_item_ref(self, ii) } - fn visit_impl_item_ref(&mut self, ii: &'v ImplItemRef<'v>) { + fn visit_impl_item_ref(&mut self, ii: &'v ImplItemRef) { walk_impl_item_ref(self, ii) } fn visit_trait_ref(&mut self, t: &'v TraitRef<'v>) { @@ -1042,22 +1042,20 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplIt pub fn walk_foreign_item_ref<'v, V: Visitor<'v>>( visitor: &mut V, - foreign_item_ref: &'v ForeignItemRef<'v>, + foreign_item_ref: &'v ForeignItemRef, ) { // N.B., deliberately force a compilation error if/when new fields are added. - let ForeignItemRef { id, ident, span: _, ref vis } = *foreign_item_ref; + let ForeignItemRef { id, ident, span: _ } = *foreign_item_ref; visitor.visit_nested_foreign_item(id); visitor.visit_ident(ident); - visitor.visit_vis(vis); } -pub fn walk_impl_item_ref<'v, V: Visitor<'v>>(visitor: &mut V, impl_item_ref: &'v ImplItemRef<'v>) { +pub fn walk_impl_item_ref<'v, V: Visitor<'v>>(visitor: &mut V, impl_item_ref: &'v ImplItemRef) { // N.B., deliberately force a compilation error if/when new fields are added. - let ImplItemRef { id, ident, ref kind, span: _, ref vis, ref defaultness } = *impl_item_ref; + let ImplItemRef { id, ident, ref kind, span: _, ref defaultness } = *impl_item_ref; visitor.visit_nested_impl_item(id); visitor.visit_ident(ident); visitor.visit_associated_item_kind(kind); - visitor.visit_vis(vis); visitor.visit_defaultness(defaultness); } diff --git a/compiler/rustc_hir_pretty/Cargo.toml b/compiler/rustc_hir_pretty/Cargo.toml index c7510b7ec14..46a8e7deeed 100644 --- a/compiler/rustc_hir_pretty/Cargo.toml +++ b/compiler/rustc_hir_pretty/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_hir_pretty" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] doctest = false diff --git a/compiler/rustc_incremental/Cargo.toml b/compiler/rustc_incremental/Cargo.toml index 9156243a10c..dece752c194 100644 --- a/compiler/rustc_incremental/Cargo.toml +++ b/compiler/rustc_incremental/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_incremental" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] doctest = false diff --git a/compiler/rustc_index/Cargo.toml b/compiler/rustc_index/Cargo.toml index e1a2b619763..b984a1321e0 100644 --- a/compiler/rustc_index/Cargo.toml +++ b/compiler/rustc_index/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_index" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] doctest = false diff --git a/compiler/rustc_infer/Cargo.toml b/compiler/rustc_infer/Cargo.toml index 15649bb678e..f87ea43b1a7 100644 --- a/compiler/rustc_infer/Cargo.toml +++ b/compiler/rustc_infer/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_infer" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] doctest = false diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 354b8e26d53..43d3730c049 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -64,6 +64,7 @@ mod lub; pub mod nll_relate; pub mod opaque_types; pub mod outlives; +mod projection; pub mod region_constraints; pub mod resolve; mod sub; diff --git a/compiler/rustc_infer/src/infer/projection.rs b/compiler/rustc_infer/src/infer/projection.rs new file mode 100644 index 00000000000..9b53ab72b00 --- /dev/null +++ b/compiler/rustc_infer/src/infer/projection.rs @@ -0,0 +1,39 @@ +use rustc_middle::traits::ObligationCause; +use rustc_middle::ty::{self, ToPredicate, Ty}; + +use crate::traits::{Obligation, PredicateObligation}; + +use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; +use super::InferCtxt; + +impl<'a, 'tcx> InferCtxt<'a, 'tcx> { + /// Instead of normalizing an associated type projection, + /// this function generates an inference variable and registers + /// an obligation that this inference variable must be the result + /// of the given projection. This allows us to proceed with projections + /// while they cannot be resolved yet due to missing information or + /// simply due to the lack of access to the trait resolution machinery. + pub fn infer_projection( + &self, + param_env: ty::ParamEnv<'tcx>, + projection_ty: ty::ProjectionTy<'tcx>, + cause: ObligationCause<'tcx>, + recursion_depth: usize, + obligations: &mut Vec<PredicateObligation<'tcx>>, + ) -> Ty<'tcx> { + let def_id = projection_ty.item_def_id; + let ty_var = self.next_ty_var(TypeVariableOrigin { + kind: TypeVariableOriginKind::NormalizeProjectionType, + span: self.tcx.def_span(def_id), + }); + let projection = ty::Binder::dummy(ty::ProjectionPredicate { projection_ty, ty: ty_var }); + let obligation = Obligation::with_depth( + cause, + recursion_depth, + param_env, + projection.to_predicate(self.tcx), + ); + obligations.push(obligation); + ty_var + } +} diff --git a/compiler/rustc_interface/Cargo.toml b/compiler/rustc_interface/Cargo.toml index e76fa6d8a1b..07af2201f5f 100644 --- a/compiler/rustc_interface/Cargo.toml +++ b/compiler/rustc_interface/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_interface" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] doctest = false diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index a5f0c014778..3d90a6c9345 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -125,6 +125,7 @@ pub fn scoped_thread<F: FnOnce() -> R + Send, R: Send>(cfg: thread::Builder, f: let result_ptr = Ptr(&mut result as *mut _ as *mut ()); let thread = cfg.spawn(move || { + let _ = (&run, &result_ptr); let run = unsafe { (*(run.0 as *mut Option<F>)).take().unwrap() }; let result = unsafe { &mut *(result_ptr.0 as *mut Option<R>) }; *result = Some(run()); diff --git a/compiler/rustc_lexer/Cargo.toml b/compiler/rustc_lexer/Cargo.toml index 7e05fe545ca..60c146f457b 100644 --- a/compiler/rustc_lexer/Cargo.toml +++ b/compiler/rustc_lexer/Cargo.toml @@ -2,7 +2,7 @@ name = "rustc_lexer" version = "0.1.0" license = "MIT OR Apache-2.0" -edition = "2018" +edition = "2021" repository = "https://github.com/rust-lang/rust/" description = """ diff --git a/compiler/rustc_lint/Cargo.toml b/compiler/rustc_lint/Cargo.toml index 8294d5878fa..414fcbeb9e4 100644 --- a/compiler/rustc_lint/Cargo.toml +++ b/compiler/rustc_lint/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_lint" version = "0.0.0" -edition = "2018" +edition = "2021" [dependencies] if_chain = "1.0" diff --git a/compiler/rustc_lint/src/array_into_iter.rs b/compiler/rustc_lint/src/array_into_iter.rs index 5ac42c50c72..1facd973754 100644 --- a/compiler/rustc_lint/src/array_into_iter.rs +++ b/compiler/rustc_lint/src/array_into_iter.rs @@ -13,7 +13,7 @@ declare_lint! { /// /// ### Example /// - /// ```rust + /// ```rust,edition2018 /// # #![allow(unused)] /// [1, 2, 3].into_iter().for_each(|n| { *n; }); /// ``` diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 2850e7a6b44..e1bcc3aa52b 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -1686,7 +1686,7 @@ declare_lint! { /// /// ### Example /// - /// ```rust + /// ```rust,edition2018 /// let x = 123; /// match x { /// 0...100 => {} diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index ef4bda666ba..10285272130 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -298,6 +298,7 @@ fn register_builtins(store: &mut LintStore, no_interleave_lints: bool) { UNUSED_LABELS, UNUSED_PARENS, UNUSED_BRACES, + MUST_NOT_SUSPEND, REDUNDANT_SEMICOLONS ); diff --git a/compiler/rustc_lint/src/non_fmt_panic.rs b/compiler/rustc_lint/src/non_fmt_panic.rs index 33a6edafa26..ae9c5ce5c3c 100644 --- a/compiler/rustc_lint/src/non_fmt_panic.rs +++ b/compiler/rustc_lint/src/non_fmt_panic.rs @@ -18,7 +18,7 @@ declare_lint! { /// /// ### Example /// - /// ```rust,no_run + /// ```rust,no_run,edition2018 /// panic!("{}"); /// panic!(123); /// ``` diff --git a/compiler/rustc_lint_defs/Cargo.toml b/compiler/rustc_lint_defs/Cargo.toml index f9ada5cc95f..798d50819e2 100644 --- a/compiler/rustc_lint_defs/Cargo.toml +++ b/compiler/rustc_lint_defs/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_lint_defs" version = "0.0.0" -edition = "2018" +edition = "2021" [dependencies] rustc_ast = { path = "../rustc_ast" } diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index a00561e5213..5830ce26fea 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -315,6 +315,44 @@ declare_lint! { } declare_lint! { + /// The `must_not_suspend` lint guards against values that shouldn't be held across suspend points + /// (`.await`) + /// + /// ### Example + /// + /// ```rust + /// #![feature(must_not_suspend)] + /// + /// #[must_not_suspend] + /// struct SyncThing {} + /// + /// async fn yield_now() {} + /// + /// pub async fn uhoh() { + /// let guard = SyncThing {}; + /// yield_now().await; + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// The `must_not_suspend` lint detects values that are marked with the `#[must_not_suspend]` + /// attribute being held across suspend points. A "suspend" point is usually a `.await` in an async + /// function. + /// + /// This attribute can be used to mark values that are semantically incorrect across suspends + /// (like certain types of timers), values that have async alternatives, and values that + /// regularly cause problems with the `Send`-ness of async fn's returned futures (like + /// `MutexGuard`'s) + /// + pub MUST_NOT_SUSPEND, + Warn, + "use of a `#[must_not_suspend]` value across a yield point", +} + +declare_lint! { /// The `unused_extern_crates` lint guards against `extern crate` items /// that are never used. /// @@ -1584,7 +1622,7 @@ declare_lint! { /// /// ### Example /// - /// ```rust + /// ```rust,edition2018 /// trait Trait { } /// /// fn takes_trait_object(_: Box<Trait>) { @@ -2993,6 +3031,7 @@ declare_lint_pass! { CENUM_IMPL_DROP_CAST, CONST_EVALUATABLE_UNCHECKED, INEFFECTIVE_UNSTABLE_TRAIT_IMPL, + MUST_NOT_SUSPEND, UNINHABITED_STATIC, FUNCTION_ITEM_REFERENCES, USELESS_DEPRECATED, @@ -3313,7 +3352,7 @@ declare_lint! { /// /// ### Example /// - /// ```rust,compile_fail + /// ```rust,edition2018,compile_fail /// #![deny(rust_2021_prefixes_incompatible_syntax)] /// /// macro_rules! m { @@ -3333,6 +3372,8 @@ declare_lint! { /// /// This lint suggests to add whitespace between the `z` and `"hey"` tokens /// to keep them separated in Rust 2021. + // Allow this lint -- rustdoc doesn't yet support threading edition into this lint's parser. + #[allow(rustdoc::invalid_rust_codeblocks)] pub RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX, Allow, "identifiers that will be parsed as a prefix in Rust 2021", diff --git a/compiler/rustc_llvm/Cargo.toml b/compiler/rustc_llvm/Cargo.toml index 2f0f3dd9ecb..d8dfcc84e68 100644 --- a/compiler/rustc_llvm/Cargo.toml +++ b/compiler/rustc_llvm/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_llvm" version = "0.0.0" -edition = "2018" +edition = "2021" [features] static-libstdcpp = [] diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 8dbacd71fc1..1a0cfd58885 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -1747,7 +1747,7 @@ LLVMRustGetBitcodeSliceFromObjectData(const char *data, // Rewrite all `DICompileUnit` pointers to the `DICompileUnit` specified. See // the comment in `back/lto.rs` for why this exists. extern "C" void -LLVMRustThinLTOGetDICompileUnit(LLVMModuleRef Mod, +LLVMRustLTOGetDICompileUnit(LLVMModuleRef Mod, DICompileUnit **A, DICompileUnit **B) { Module *M = unwrap(Mod); @@ -1765,7 +1765,7 @@ LLVMRustThinLTOGetDICompileUnit(LLVMModuleRef Mod, // Rewrite all `DICompileUnit` pointers to the `DICompileUnit` specified. See // the comment in `back/lto.rs` for why this exists. extern "C" void -LLVMRustThinLTOPatchDICompileUnit(LLVMModuleRef Mod, DICompileUnit *Unit) { +LLVMRustLTOPatchDICompileUnit(LLVMModuleRef Mod, DICompileUnit *Unit) { Module *M = unwrap(Mod); // If the original source module didn't have a `DICompileUnit` then try to diff --git a/compiler/rustc_macros/Cargo.toml b/compiler/rustc_macros/Cargo.toml index e4dddbab067..a9192be4d6e 100644 --- a/compiler/rustc_macros/Cargo.toml +++ b/compiler/rustc_macros/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_macros" version = "0.1.0" -edition = "2018" +edition = "2021" [lib] proc-macro = true diff --git a/compiler/rustc_metadata/Cargo.toml b/compiler/rustc_metadata/Cargo.toml index 42596f3318d..f71fefd1799 100644 --- a/compiler/rustc_metadata/Cargo.toml +++ b/compiler/rustc_metadata/Cargo.toml @@ -1,14 +1,14 @@ [package] name = "rustc_metadata" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] doctest = false [dependencies] libc = "0.2" -odht = { version = "0.2.1", features = ["nightly"] } +odht = { version = "0.3.0", features = ["nightly"] } snap = "1" tracing = "0.1" smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } diff --git a/compiler/rustc_metadata/src/dependency_format.rs b/compiler/rustc_metadata/src/dependency_format.rs index b8d22560618..8c41fd9c4a2 100644 --- a/compiler/rustc_metadata/src/dependency_format.rs +++ b/compiler/rustc_metadata/src/dependency_format.rs @@ -11,10 +11,10 @@ //! should be used when linking each output type requested in this session. This //! generally follows this set of rules: //! -//! 1. Each library must appear exactly once in the output. -//! 2. Each rlib contains only one library (it's just an object file) -//! 3. Each dylib can contain more than one library (due to static linking), -//! and can also bring in many dynamic dependencies. +//! 1. Each library must appear exactly once in the output. +//! 2. Each rlib contains only one library (it's just an object file) +//! 3. Each dylib can contain more than one library (due to static linking), +//! and can also bring in many dynamic dependencies. //! //! With these constraints in mind, it's generally a very difficult problem to //! find a solution that's not "all rlibs" or "all dylibs". I have suspicions @@ -22,24 +22,24 @@ //! //! The current selection algorithm below looks mostly similar to: //! -//! 1. If static linking is required, then require all upstream dependencies -//! to be available as rlibs. If not, generate an error. -//! 2. If static linking is requested (generating an executable), then -//! attempt to use all upstream dependencies as rlibs. If any are not -//! found, bail out and continue to step 3. -//! 3. Static linking has failed, at least one library must be dynamically -//! linked. Apply a heuristic by greedily maximizing the number of -//! dynamically linked libraries. -//! 4. Each upstream dependency available as a dynamic library is -//! registered. The dependencies all propagate, adding to a map. It is -//! possible for a dylib to add a static library as a dependency, but it -//! is illegal for two dylibs to add the same static library as a -//! dependency. The same dylib can be added twice. Additionally, it is -//! illegal to add a static dependency when it was previously found as a -//! dylib (and vice versa) -//! 5. After all dynamic dependencies have been traversed, re-traverse the -//! remaining dependencies and add them statically (if they haven't been -//! added already). +//! 1. If static linking is required, then require all upstream dependencies +//! to be available as rlibs. If not, generate an error. +//! 2. If static linking is requested (generating an executable), then +//! attempt to use all upstream dependencies as rlibs. If any are not +//! found, bail out and continue to step 3. +//! 3. Static linking has failed, at least one library must be dynamically +//! linked. Apply a heuristic by greedily maximizing the number of +//! dynamically linked libraries. +//! 4. Each upstream dependency available as a dynamic library is +//! registered. The dependencies all propagate, adding to a map. It is +//! possible for a dylib to add a static library as a dependency, but it +//! is illegal for two dylibs to add the same static library as a +//! dependency. The same dylib can be added twice. Additionally, it is +//! illegal to add a static dependency when it was previously found as a +//! dylib (and vice versa) +//! 5. After all dynamic dependencies have been traversed, re-traverse the +//! remaining dependencies and add them statically (if they haven't been +//! added already). //! //! While not perfect, this algorithm should help support use-cases such as leaf //! dependencies being static while the larger tree of inner dependencies are diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index 5f0d8c46f20..5ad55dbf5c8 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -382,7 +382,7 @@ impl Collector<'tcx> { } } - fn i686_arg_list_size(&self, item: &hir::ForeignItemRef<'_>) -> usize { + fn i686_arg_list_size(&self, item: &hir::ForeignItemRef) -> usize { let argument_types: &List<Ty<'_>> = self.tcx.erase_late_bound_regions( self.tcx .type_of(item.id.def_id) @@ -406,7 +406,7 @@ impl Collector<'tcx> { .sum() } - fn build_dll_import(&self, abi: Abi, item: &hir::ForeignItemRef<'_>) -> DllImport { + fn build_dll_import(&self, abi: Abi, item: &hir::ForeignItemRef) -> DllImport { let calling_convention = if self.tcx.sess.target.arch == "x86" { match abi { Abi::C { .. } | Abi::Cdecl => DllCallingConvention::C, diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml index 68b83fccc85..b1fcc34bee1 100644 --- a/compiler/rustc_middle/Cargo.toml +++ b/compiler/rustc_middle/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_middle" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] doctest = false diff --git a/compiler/rustc_middle/src/hir/map/collector.rs b/compiler/rustc_middle/src/hir/map/collector.rs index 082948eba41..5ecb1c9b0ff 100644 --- a/compiler/rustc_middle/src/hir/map/collector.rs +++ b/compiler/rustc_middle/src/hir/map/collector.rs @@ -413,18 +413,18 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { self.visit_nested_trait_item(id); } - fn visit_impl_item_ref(&mut self, ii: &'hir ImplItemRef<'hir>) { + fn visit_impl_item_ref(&mut self, ii: &'hir ImplItemRef) { // Do not visit the duplicate information in ImplItemRef. We want to // map the actual nodes, not the duplicate ones in the *Ref. - let ImplItemRef { id, ident: _, kind: _, span: _, vis: _, defaultness: _ } = *ii; + let ImplItemRef { id, ident: _, kind: _, span: _, defaultness: _ } = *ii; self.visit_nested_impl_item(id); } - fn visit_foreign_item_ref(&mut self, fi: &'hir ForeignItemRef<'hir>) { + fn visit_foreign_item_ref(&mut self, fi: &'hir ForeignItemRef) { // Do not visit the duplicate information in ForeignItemRef. We want to // map the actual nodes, not the duplicate ones in the *Ref. - let ForeignItemRef { id, ident: _, span: _, vis: _ } = *fi; + let ForeignItemRef { id, ident: _, span: _ } = *fi; self.visit_nested_foreign_item(id); } diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 0c2c653e92e..3707fadadac 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -83,12 +83,12 @@ pub struct Map<'hir> { /// An iterator that walks up the ancestor tree of a given `HirId`. /// Constructed using `tcx.hir().parent_iter(hir_id)`. -pub struct ParentHirIterator<'map, 'hir> { +pub struct ParentHirIterator<'hir> { current_id: HirId, - map: &'map Map<'hir>, + map: Map<'hir>, } -impl<'hir> Iterator for ParentHirIterator<'_, 'hir> { +impl<'hir> Iterator for ParentHirIterator<'hir> { type Item = (HirId, Node<'hir>); fn next(&mut self) -> Option<Self::Item> { @@ -115,12 +115,12 @@ impl<'hir> Iterator for ParentHirIterator<'_, 'hir> { /// An iterator that walks up the ancestor tree of a given `HirId`. /// Constructed using `tcx.hir().parent_owner_iter(hir_id)`. -pub struct ParentOwnerIterator<'map, 'hir> { +pub struct ParentOwnerIterator<'hir> { current_id: HirId, - map: &'map Map<'hir>, + map: Map<'hir>, } -impl<'hir> Iterator for ParentOwnerIterator<'_, 'hir> { +impl<'hir> Iterator for ParentOwnerIterator<'hir> { type Item = (HirId, OwnerNode<'hir>); fn next(&mut self) -> Option<Self::Item> { @@ -588,13 +588,13 @@ impl<'hir> Map<'hir> { /// 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> { + pub fn parent_iter(self, current_id: HirId) -> ParentHirIterator<'hir> { ParentHirIterator { current_id, map: self } } /// 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_owner_iter(&self, current_id: HirId) -> ParentOwnerIterator<'_, 'hir> { + pub fn parent_owner_iter(self, current_id: HirId) -> ParentOwnerIterator<'hir> { ParentOwnerIterator { current_id, map: self } } diff --git a/compiler/rustc_middle/src/ich/impls_ty.rs b/compiler/rustc_middle/src/ich/impls_ty.rs index 8e53e4ba948..3b0640eb98d 100644 --- a/compiler/rustc_middle/src/ich/impls_ty.rs +++ b/compiler/rustc_middle/src/ich/impls_ty.rs @@ -90,7 +90,10 @@ impl<'a> HashStable<StableHashingContext<'a>> for ty::RegionKind { ty::ReFree(ref free_region) => { free_region.hash_stable(hcx, hasher); } - ty::ReVar(..) | ty::RePlaceholder(..) => { + ty::RePlaceholder(p) => { + p.hash_stable(hcx, hasher); + } + ty::ReVar(..) => { bug!("StableHasher: unexpected region {:?}", *self) } } diff --git a/compiler/rustc_middle/src/middle/region.rs b/compiler/rustc_middle/src/middle/region.rs index bd4e83a42ef..e271f59da87 100644 --- a/compiler/rustc_middle/src/middle/region.rs +++ b/compiler/rustc_middle/src/middle/region.rs @@ -257,7 +257,8 @@ pub struct ScopeTree { /// ``` /// /// With the HIR tree (calls numbered for expository purposes) - /// ``` + /// + /// ```text /// Call#0(foo, [Call#1(f), Yield(y), Call#2(bar, Call#3(g))]) /// ``` /// diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 9d1be212f5b..2c786538014 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -639,6 +639,15 @@ fn check_const_value_eq<R: TypeRelation<'tcx>>( get_slice_bytes(&tcx, a_val) == get_slice_bytes(&tcx, b_val) } + (ConstValue::ByRef { alloc: alloc_a, .. }, ConstValue::ByRef { alloc: alloc_b, .. }) + if a.ty.is_ref() || b.ty.is_ref() => + { + if a.ty.is_ref() && b.ty.is_ref() { + alloc_a == alloc_b + } else { + false + } + } (ConstValue::ByRef { .. }, ConstValue::ByRef { .. }) => { let a_destructured = tcx.destructure_const(relation.param_env().and(a)); let b_destructured = tcx.destructure_const(relation.param_env().and(b)); diff --git a/compiler/rustc_mir_build/Cargo.toml b/compiler/rustc_mir_build/Cargo.toml index e9fbc1b186d..998b80a36c2 100644 --- a/compiler/rustc_mir_build/Cargo.toml +++ b/compiler/rustc_mir_build/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_mir_build" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] doctest = false diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 0ee740a6463..4108ad50470 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -44,15 +44,18 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_ let body_owner_kind = tcx.hir().body_owner_kind(id); let typeck_results = tcx.typeck_opt_const_arg(def); - // Ensure unsafeck is ran before we steal the THIR. + // Ensure unsafeck and abstract const building is ran before we steal the THIR. + // We can't use `ensure()` for `thir_abstract_const` as it doesn't compute the query + // if inputs are green. This can cause ICEs when calling `thir_abstract_const` after + // THIR has been stolen if we haven't computed this query yet. match def { ty::WithOptConstParam { did, const_param_did: Some(const_param_did) } => { tcx.ensure().thir_check_unsafety_for_const_arg((did, const_param_did)); - tcx.ensure().thir_abstract_const_of_const_arg((did, const_param_did)); + drop(tcx.thir_abstract_const_of_const_arg((did, const_param_did))); } ty::WithOptConstParam { did, const_param_did: None } => { tcx.ensure().thir_check_unsafety(did); - tcx.ensure().thir_abstract_const(did); + drop(tcx.thir_abstract_const(did)); } } diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index bbb5de34d18..847b89f0464 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -322,16 +322,18 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> { && !self.saw_const_match_lint.get() { self.saw_const_match_lint.set(true); - let msg = format!( - "to use a constant of type `{}` in a pattern, \ - `{}` must be annotated with `#[derive(PartialEq, Eq)]`", - cv.ty, cv.ty, - ); tcx.struct_span_lint_hir( lint::builtin::INDIRECT_STRUCTURAL_MATCH, id, span, - |lint| lint.build(&msg).emit(), + |lint| { + let msg = format!( + "to use a constant of type `{}` in a pattern, \ + `{}` must be annotated with `#[derive(PartialEq, Eq)]`", + cv.ty, cv.ty, + ); + lint.build(&msg).emit() + }, ); } // Since we are behind a reference, we can just bubble the error up so we get a diff --git a/compiler/rustc_mir_dataflow/Cargo.toml b/compiler/rustc_mir_dataflow/Cargo.toml index 3cd4892402e..ffd7e3cd06b 100644 --- a/compiler/rustc_mir_dataflow/Cargo.toml +++ b/compiler/rustc_mir_dataflow/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_mir_dataflow" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] doctest = false diff --git a/compiler/rustc_mir_transform/Cargo.toml b/compiler/rustc_mir_transform/Cargo.toml index 5e1a587b0ec..bde4e215a2a 100644 --- a/compiler/rustc_mir_transform/Cargo.toml +++ b/compiler/rustc_mir_transform/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_mir_transform" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] doctest = false diff --git a/compiler/rustc_mir_transform/src/coverage/test_macros/Cargo.toml b/compiler/rustc_mir_transform/src/coverage/test_macros/Cargo.toml index cc93fd482b5..f5e8b65656a 100644 --- a/compiler/rustc_mir_transform/src/coverage/test_macros/Cargo.toml +++ b/compiler/rustc_mir_transform/src/coverage/test_macros/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "coverage_test_macros" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] proc-macro = true diff --git a/compiler/rustc_monomorphize/Cargo.toml b/compiler/rustc_monomorphize/Cargo.toml index 350ae088777..f812afe6b62 100644 --- a/compiler/rustc_monomorphize/Cargo.toml +++ b/compiler/rustc_monomorphize/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_monomorphize" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] doctest = false diff --git a/compiler/rustc_parse/Cargo.toml b/compiler/rustc_parse/Cargo.toml index 1ca1a92252e..1decaaa955f 100644 --- a/compiler/rustc_parse/Cargo.toml +++ b/compiler/rustc_parse/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_parse" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] doctest = false diff --git a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs index aa6b424ce2b..cef5b3a226b 100644 --- a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs +++ b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs @@ -3,7 +3,7 @@ use std::iter::once; use std::ops::Range; -use rustc_errors::{Applicability, Handler}; +use rustc_errors::{pluralize, Applicability, Handler}; use rustc_lexer::unescape::{EscapeError, Mode}; use rustc_span::{BytePos, Span}; @@ -49,24 +49,57 @@ pub(crate) fn emit_unescape_error( .emit(); } EscapeError::MoreThanOneChar => { - let (prefix, msg) = if mode.is_bytes() { - ("b", "if you meant to write a byte string literal, use double quotes") - } else { - ("", "if you meant to write a `str` literal, use double quotes") - }; + use unicode_normalization::{char::is_combining_mark, UnicodeNormalization}; - handler - .struct_span_err( - span_with_quotes, - "character literal may only contain one codepoint", - ) - .span_suggestion( + let mut has_help = false; + let mut handler = handler.struct_span_err( + span_with_quotes, + "character literal may only contain one codepoint", + ); + + if lit.chars().skip(1).all(|c| is_combining_mark(c)) { + let escaped_marks = + lit.chars().skip(1).map(|c| c.escape_default().to_string()).collect::<Vec<_>>(); + handler.span_note( + span, + &format!( + "this `{}` is followed by the combining mark{} `{}`", + lit.chars().next().unwrap(), + pluralize!(escaped_marks.len()), + escaped_marks.join(""), + ), + ); + let normalized = lit.nfc().to_string(); + if normalized.chars().count() == 1 { + has_help = true; + handler.span_suggestion( + span, + &format!( + "consider using the normalized form `{}` of this character", + normalized.chars().next().unwrap().escape_default() + ), + normalized, + Applicability::MachineApplicable, + ); + } + } + + if !has_help { + let (prefix, msg) = if mode.is_bytes() { + ("b", "if you meant to write a byte string literal, use double quotes") + } else { + ("", "if you meant to write a `str` literal, use double quotes") + }; + + handler.span_suggestion( span_with_quotes, msg, format!("{}\"{}\"", prefix, lit), Applicability::MachineApplicable, - ) - .emit(); + ); + } + + handler.emit(); } EscapeError::EscapeOnlyChar => { let (c, char_span) = last_char(); diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index af41a99ada4..a40f47f895b 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -6,6 +6,9 @@ #![feature(box_patterns)] #![recursion_limit = "256"] +#[macro_use] +extern crate tracing; + use rustc_ast as ast; use rustc_ast::token::{self, Nonterminal, Token, TokenKind}; use rustc_ast::tokenstream::{self, AttributesData, CanSynthesizeMissingTokens, LazyTokenStream}; diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index d8f9fc9179e..fe0468c6956 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1084,6 +1084,7 @@ impl<'a> Parser<'a> { /// If we encounter a parser state that looks like the user has written a `struct` literal with /// parentheses instead of braces, recover the parser state and provide suggestions. + #[instrument(skip(self, seq, snapshot), level = "trace")] fn maybe_recover_struct_lit_bad_delims( &mut self, lo: Span, @@ -1204,7 +1205,7 @@ impl<'a> Parser<'a> { } else if self.check(&token::BinOp(token::Or)) || self.check(&token::OrOr) { self.parse_closure_expr(attrs) } else if self.check(&token::OpenDelim(token::Bracket)) { - self.parse_array_or_repeat_expr(attrs) + self.parse_array_or_repeat_expr(attrs, token::Bracket) } else if self.check_path() { self.parse_path_start_expr(attrs) } else if self.check_keyword(kw::Move) || self.check_keyword(kw::Static) { @@ -1322,11 +1323,15 @@ impl<'a> Parser<'a> { self.maybe_recover_from_bad_qpath(expr, true) } - fn parse_array_or_repeat_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> { + fn parse_array_or_repeat_expr( + &mut self, + attrs: AttrVec, + close_delim: token::DelimToken, + ) -> PResult<'a, P<Expr>> { let lo = self.token.span; - self.bump(); // `[` + self.bump(); // `[` or other open delim - let close = &token::CloseDelim(token::Bracket); + let close = &token::CloseDelim(close_delim); let kind = if self.eat(close) { // Empty vector ExprKind::Array(Vec::new()) @@ -1752,6 +1757,46 @@ impl<'a> Parser<'a> { } } + fn is_array_like_block(&mut self) -> bool { + self.look_ahead(1, |t| matches!(t.kind, TokenKind::Ident(..) | TokenKind::Literal(_))) + && self.look_ahead(2, |t| t == &token::Comma) + && self.look_ahead(3, |t| t.can_begin_expr()) + } + + /// Emits a suggestion if it looks like the user meant an array but + /// accidentally used braces, causing the code to be interpreted as a block + /// expression. + fn maybe_suggest_brackets_instead_of_braces( + &mut self, + lo: Span, + attrs: AttrVec, + ) -> Option<P<Expr>> { + let mut snapshot = self.clone(); + match snapshot.parse_array_or_repeat_expr(attrs, token::Brace) { + Ok(arr) => { + let hi = snapshot.prev_token.span; + self.struct_span_err( + arr.span, + "this code is interpreted as a block expression, not an array", + ) + .multipart_suggestion( + "try using [] instead of {}", + vec![(lo, "[".to_owned()), (hi, "]".to_owned())], + Applicability::MaybeIncorrect, + ) + .note("to define an array, one would use square brackets instead of curly braces") + .emit(); + + *self = snapshot; + Some(self.mk_expr_err(arr.span)) + } + Err(mut e) => { + e.cancel(); + None + } + } + } + /// Parses a block or unsafe block. pub(super) fn parse_block_expr( &mut self, @@ -1760,6 +1805,12 @@ impl<'a> Parser<'a> { blk_mode: BlockCheckMode, mut attrs: AttrVec, ) -> PResult<'a, P<Expr>> { + if self.is_array_like_block() { + if let Some(arr) = self.maybe_suggest_brackets_instead_of_braces(lo, attrs.clone()) { + return Ok(arr); + } + } + if let Some(label) = opt_label { self.sess.gated_spans.gate(sym::label_break_value, label.ident.span); } diff --git a/compiler/rustc_parse_format/Cargo.toml b/compiler/rustc_parse_format/Cargo.toml index 7b77560717e..aa1714e820f 100644 --- a/compiler/rustc_parse_format/Cargo.toml +++ b/compiler/rustc_parse_format/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_parse_format" version = "0.0.0" -edition = "2018" +edition = "2021" [dependencies] rustc_span = { path = "../rustc_span" } diff --git a/compiler/rustc_passes/Cargo.toml b/compiler/rustc_passes/Cargo.toml index bf1e52cd9a8..39e578bce7e 100644 --- a/compiler/rustc_passes/Cargo.toml +++ b/compiler/rustc_passes/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_passes" version = "0.0.0" -edition = "2018" +edition = "2021" [dependencies] tracing = "0.1" diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index fd438bdc900..3e59fc4f551 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -104,6 +104,7 @@ impl CheckAttrVisitor<'tcx> { sym::default_method_body_is_const => { self.check_default_method_body_is_const(attr, span, target) } + sym::must_not_suspend => self.check_must_not_suspend(&attr, span, target), sym::rustc_const_unstable | sym::rustc_const_stable | sym::unstable @@ -1014,6 +1015,21 @@ impl CheckAttrVisitor<'tcx> { is_valid } + /// Checks if `#[must_not_suspend]` is applied to a function. Returns `true` if valid. + fn check_must_not_suspend(&self, attr: &Attribute, span: &Span, target: Target) -> bool { + match target { + Target::Struct | Target::Enum | Target::Union | Target::Trait => true, + _ => { + self.tcx + .sess + .struct_span_err(attr.span, "`must_not_suspend` attribute should be applied to a struct, enum, or trait") + .span_label(*span, "is not a struct, enum, or trait") + .emit(); + false + } + } + } + /// Checks if `#[cold]` is applied to a non-function. Returns `true` if valid. fn check_cold(&self, hir_id: HirId, attr: &Attribute, span: &Span, target: Target) { match target { diff --git a/compiler/rustc_passes/src/hir_id_validator.rs b/compiler/rustc_passes/src/hir_id_validator.rs index eff1096c855..0e60ca9f900 100644 --- a/compiler/rustc_passes/src/hir_id_validator.rs +++ b/compiler/rustc_passes/src/hir_id_validator.rs @@ -163,14 +163,14 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirIdValidator<'a, 'hir> { self.hir_ids_seen.insert(hir_id.local_id); } - fn visit_impl_item_ref(&mut self, _: &'hir hir::ImplItemRef<'hir>) { + fn visit_impl_item_ref(&mut self, _: &'hir hir::ImplItemRef) { // Explicitly do nothing here. ImplItemRefs contain hir::Visibility // values that actually belong to an ImplItem instead of the ItemKind::Impl // we are currently in. So for those it's correct that they have a // different owner. } - fn visit_foreign_item_ref(&mut self, _: &'hir hir::ForeignItemRef<'hir>) { + fn visit_foreign_item_ref(&mut self, _: &'hir hir::ForeignItemRef) { // Explicitly do nothing here. ForeignItemRefs contain hir::Visibility // values that actually belong to an ForeignItem instead of the ItemKind::ForeignMod // we are currently in. So for those it's correct that they have a diff --git a/compiler/rustc_plugin_impl/Cargo.toml b/compiler/rustc_plugin_impl/Cargo.toml index c8eaca0703c..4e666e7e93d 100644 --- a/compiler/rustc_plugin_impl/Cargo.toml +++ b/compiler/rustc_plugin_impl/Cargo.toml @@ -2,7 +2,7 @@ name = "rustc_plugin_impl" version = "0.0.0" build = false -edition = "2018" +edition = "2021" [lib] doctest = false diff --git a/compiler/rustc_privacy/Cargo.toml b/compiler/rustc_privacy/Cargo.toml index 6ac2915c345..d952e288a64 100644 --- a/compiler/rustc_privacy/Cargo.toml +++ b/compiler/rustc_privacy/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_privacy" version = "0.0.0" -edition = "2018" +edition = "2021" [dependencies] rustc_middle = { path = "../rustc_middle" } diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 391e4305423..e14f758ddae 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -743,7 +743,9 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> { } hir::ItemKind::Impl(ref impl_) => { for impl_item_ref in impl_.items { - if impl_.of_trait.is_some() || impl_item_ref.vis.node.is_pub() { + if impl_.of_trait.is_some() + || self.tcx.visibility(impl_item_ref.id.def_id) == ty::Visibility::Public + { self.update(impl_item_ref.id.def_id, item_level); } } @@ -768,7 +770,7 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> { } hir::ItemKind::ForeignMod { items, .. } => { for foreign_item in items { - if foreign_item.vis.node.is_pub() { + if self.tcx.visibility(foreign_item.id.def_id) == ty::Visibility::Public { self.update(foreign_item.id.def_id, item_level); } } @@ -1678,7 +1680,10 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { // methods will be visible as `Public::foo`. let mut found_pub_static = false; for impl_item_ref in impl_.items { - if self.item_is_public(impl_item_ref.id.def_id, &impl_item_ref.vis) { + if self.access_levels.is_reachable(impl_item_ref.id.def_id) + || self.tcx.visibility(impl_item_ref.id.def_id) + == ty::Visibility::Public + { let impl_item = self.tcx.hir().impl_item(impl_item_ref.id); match impl_item_ref.kind { AssocItemKind::Const => { diff --git a/compiler/rustc_query_impl/Cargo.toml b/compiler/rustc_query_impl/Cargo.toml index 7c8dbe34240..89df3d4674b 100644 --- a/compiler/rustc_query_impl/Cargo.toml +++ b/compiler/rustc_query_impl/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_query_impl" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] doctest = false diff --git a/compiler/rustc_query_system/Cargo.toml b/compiler/rustc_query_system/Cargo.toml index 47fb78be640..11c18a497e5 100644 --- a/compiler/rustc_query_system/Cargo.toml +++ b/compiler/rustc_query_system/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_query_system" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] doctest = false diff --git a/compiler/rustc_resolve/Cargo.toml b/compiler/rustc_resolve/Cargo.toml index 1581b056275..f1d3315d6e6 100644 --- a/compiler/rustc_resolve/Cargo.toml +++ b/compiler/rustc_resolve/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_resolve" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] test = false diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index a158e0e48e8..84e7c68713f 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -522,8 +522,7 @@ fn item_for(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> LocalDefId { _ => {} } let item = { - let hir = tcx.hir(); - let mut parent_iter = hir.parent_iter(hir_id); + let mut parent_iter = tcx.hir().parent_iter(hir_id); loop { let node = parent_iter.next().map(|n| n.1); match node { diff --git a/compiler/rustc_save_analysis/Cargo.toml b/compiler/rustc_save_analysis/Cargo.toml index 535a48bcda1..15a89d82fa6 100644 --- a/compiler/rustc_save_analysis/Cargo.toml +++ b/compiler/rustc_save_analysis/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_save_analysis" version = "0.0.0" -edition = "2018" +edition = "2021" [dependencies] tracing = "0.1" diff --git a/compiler/rustc_serialize/Cargo.toml b/compiler/rustc_serialize/Cargo.toml index 593a7563e36..49778f82253 100644 --- a/compiler/rustc_serialize/Cargo.toml +++ b/compiler/rustc_serialize/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_serialize" version = "0.0.0" -edition = "2018" +edition = "2021" [dependencies] indexmap = "1" diff --git a/compiler/rustc_session/Cargo.toml b/compiler/rustc_session/Cargo.toml index 5b617a2997c..4cff21bee3d 100644 --- a/compiler/rustc_session/Cargo.toml +++ b/compiler/rustc_session/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_session" version = "0.0.0" -edition = "2018" +edition = "2021" [dependencies] getopts = "0.2" diff --git a/compiler/rustc_span/Cargo.toml b/compiler/rustc_span/Cargo.toml index e475e89d87e..781fb8c1e5d 100644 --- a/compiler/rustc_span/Cargo.toml +++ b/compiler/rustc_span/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_span" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] doctest = false diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 9c5469f635f..032ae73bbf3 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -25,6 +25,9 @@ #[macro_use] extern crate rustc_macros; +#[macro_use] +extern crate tracing; + use rustc_data_structures::AtomicRef; use rustc_macros::HashStable_Generic; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; @@ -782,13 +785,30 @@ impl Span { /// ^^^^^^^^^^^^^^^^^ /// ``` pub fn until(self, end: Span) -> Span { - let span = self.data(); - let end = end.data(); + // Most of this function's body is copied from `to`. + // We can't just do `self.to(end.shrink_to_lo())`, + // because to also does some magic where it uses min/max so + // it can handle overlapping spans. Some advanced mis-use of + // `until` with different ctxts makes this visible. + let span_data = self.data(); + let end_data = end.data(); + // FIXME(jseyfried): `self.ctxt` should always equal `end.ctxt` here (cf. issue #23480). + // Return the macro span on its own to avoid weird diagnostic output. It is preferable to + // have an incomplete span than a completely nonsensical one. + if span_data.ctxt != end_data.ctxt { + if span_data.ctxt == SyntaxContext::root() { + return end; + } else if end_data.ctxt == SyntaxContext::root() { + return self; + } + // Both spans fall within a macro. + // FIXME(estebank): check if it is the *same* macro. + } Span::new( - span.lo, - end.lo, - if end.ctxt == SyntaxContext::root() { end.ctxt } else { span.ctxt }, - if span.parent == end.parent { span.parent } else { None }, + span_data.lo, + end_data.lo, + if end_data.ctxt == SyntaxContext::root() { end_data.ctxt } else { span_data.ctxt }, + if span_data.parent == end_data.parent { span_data.parent } else { None }, ) } diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs index 9e403eb3f67..b79f00a8a36 100644 --- a/compiler/rustc_span/src/source_map.rs +++ b/compiler/rustc_span/src/source_map.rs @@ -474,11 +474,12 @@ impl SourceMap { f.lookup_line(sp.lo()) != f.lookup_line(sp.hi()) } + #[instrument(skip(self), level = "trace")] pub fn is_valid_span(&self, sp: Span) -> Result<(Loc, Loc), SpanLinesError> { let lo = self.lookup_char_pos(sp.lo()); - debug!("span_to_lines: lo={:?}", lo); + trace!(?lo); let hi = self.lookup_char_pos(sp.hi()); - debug!("span_to_lines: hi={:?}", hi); + trace!(?hi); if lo.file.start_pos != hi.file.start_pos { return Err(SpanLinesError::DistinctSources(DistinctSources { begin: (lo.file.name.clone(), lo.file.start_pos), diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 322bea3806c..7c2a09e0a32 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -837,6 +837,7 @@ symbols! { mul, mul_assign, mul_with_overflow, + must_not_suspend, must_use, mut_ptr, mut_slice_ptr, diff --git a/compiler/rustc_symbol_mangling/Cargo.toml b/compiler/rustc_symbol_mangling/Cargo.toml index aebf77a1fd8..d5befa10e23 100644 --- a/compiler/rustc_symbol_mangling/Cargo.toml +++ b/compiler/rustc_symbol_mangling/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_symbol_mangling" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] doctest = false diff --git a/compiler/rustc_target/Cargo.toml b/compiler/rustc_target/Cargo.toml index e47a84dbc11..925813e6bb4 100644 --- a/compiler/rustc_target/Cargo.toml +++ b/compiler/rustc_target/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_target" version = "0.0.0" -edition = "2018" +edition = "2021" [dependencies] bitflags = "1.2.1" diff --git a/compiler/rustc_trait_selection/Cargo.toml b/compiler/rustc_trait_selection/Cargo.toml index e2c626d1b22..9a9737362c6 100644 --- a/compiler/rustc_trait_selection/Cargo.toml +++ b/compiler/rustc_trait_selection/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_trait_selection" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] doctest = false diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs index 8abcdb5e89b..c01faae5d6a 100644 --- a/compiler/rustc_trait_selection/src/opaque_types.rs +++ b/compiler/rustc_trait_selection/src/opaque_types.rs @@ -1,4 +1,3 @@ -use crate::infer::InferCtxtExt as _; use crate::traits::{self, ObligationCause, PredicateObligation}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; @@ -863,7 +862,6 @@ struct Instantiator<'a, 'tcx> { } impl<'a, 'tcx> Instantiator<'a, 'tcx> { - #[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 { @@ -954,6 +952,7 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { }) } + #[instrument(skip(self), level = "debug")] fn fold_opaque_ty( &mut self, ty: Ty<'tcx>, @@ -964,25 +963,18 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { let tcx = infcx.tcx; let OpaqueTypeKey { def_id, substs } = opaque_type_key; - debug!("instantiate_opaque_types: Opaque(def_id={:?}, substs={:?})", def_id, substs); - // Use the same type variable if the exact same opaque type appears more // than once in the return type (e.g., if it's passed to a type alias). if let Some(opaque_defn) = infcx.inner.borrow().opaque_types.get(&opaque_type_key) { - debug!("instantiate_opaque_types: returning concrete ty {:?}", opaque_defn.concrete_ty); + debug!("re-using cached concrete type {:?}", opaque_defn.concrete_ty.kind()); return opaque_defn.concrete_ty; } + let ty_var = infcx.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span: self.value_span, }); - // Make sure that we are in fact defining the *entire* type - // (e.g., `type Foo<T: Bound> = impl Bar;` needs to be - // defined by a function like `fn foo<T: Bound>() -> Foo<T>`). - debug!("instantiate_opaque_types: param_env={:#?}", self.param_env,); - debug!("instantiate_opaque_types: generics={:#?}", tcx.generics_of(def_id),); - // Ideally, we'd get the span where *this specific `ty` came // from*, but right now we just use the span from the overall // value being folded. In simple cases like `-> impl Foo`, @@ -999,43 +991,40 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { infcx.opaque_types_vars.insert(ty_var, ty); } - debug!("instantiate_opaque_types: ty_var={:?}", ty_var); - self.compute_opaque_type_obligations(opaque_type_key); - - ty_var - } - - fn compute_opaque_type_obligations(&mut self, opaque_type_key: OpaqueTypeKey<'tcx>) { - let infcx = self.infcx; - let tcx = infcx.tcx; - let OpaqueTypeKey { def_id, substs } = opaque_type_key; + debug!("generated new type inference var {:?}", ty_var.kind()); let item_bounds = tcx.explicit_item_bounds(def_id); - debug!("instantiate_opaque_types: bounds={:#?}", item_bounds); - let bounds: Vec<_> = - item_bounds.iter().map(|(bound, _)| bound.subst(tcx, substs)).collect(); - - let param_env = tcx.param_env(def_id); - let InferOk { value: bounds, obligations } = infcx.partially_normalize_associated_types_in( - ObligationCause::misc(self.value_span, self.body_id), - param_env, - bounds, - ); - self.obligations.extend(obligations); - debug!("instantiate_opaque_types: bounds={:?}", bounds); + self.obligations.reserve(item_bounds.len()); + for (predicate, _) in item_bounds { + debug!(?predicate); + let predicate = predicate.subst(tcx, substs); + debug!(?predicate); + + // We can't normalize associated types from `rustc_infer`, but we can eagerly register inference variables for them. + let predicate = predicate.fold_with(&mut BottomUpFolder { + tcx, + ty_op: |ty| match ty.kind() { + ty::Projection(projection_ty) => infcx.infer_projection( + self.param_env, + *projection_ty, + ObligationCause::misc(self.value_span, self.body_id), + 0, + &mut self.obligations, + ), + _ => ty, + }, + lt_op: |lt| lt, + ct_op: |ct| ct, + }); + debug!(?predicate); - for predicate in &bounds { if let ty::PredicateKind::Projection(projection) = predicate.kind().skip_binder() { if projection.ty.references_error() { // No point on adding these obligations since there's a type error involved. - return; + return tcx.ty_error(); } } - } - - self.obligations.reserve(bounds.len()); - for predicate in bounds { // Change the predicate to refer to the type variable, // which will be the concrete type instead of the opaque type. // This also instantiates nested instances of `impl Trait`. @@ -1045,9 +1034,11 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { traits::ObligationCause::new(self.value_span, self.body_id, traits::OpaqueType); // Require that the predicate holds for the concrete type. - debug!("instantiate_opaque_types: predicate={:?}", predicate); + debug!(?predicate); self.obligations.push(traits::Obligation::new(cause, self.param_env, predicate)); } + + ty_var } } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 4f22543950c..58589e556f2 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -810,17 +810,7 @@ pub fn normalize_projection_type<'a, 'b, 'tcx>( // and a deferred predicate to resolve this when more type // information is available. - let tcx = selcx.infcx().tcx; - let def_id = projection_ty.item_def_id; - let ty_var = selcx.infcx().next_ty_var(TypeVariableOrigin { - kind: TypeVariableOriginKind::NormalizeProjectionType, - span: tcx.def_span(def_id), - }); - let projection = ty::Binder::dummy(ty::ProjectionPredicate { projection_ty, ty: ty_var }); - let obligation = - Obligation::with_depth(cause, depth + 1, param_env, projection.to_predicate(tcx)); - obligations.push(obligation); - ty_var + selcx.infcx().infer_projection(param_env, projection_ty, cause, depth + 1, obligations) }) } @@ -844,6 +834,10 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>( obligations: &mut Vec<PredicateObligation<'tcx>>, ) -> Result<Option<Ty<'tcx>>, InProgress> { let infcx = selcx.infcx(); + // Don't use the projection cache in intercrate mode - + // the `infcx` may be re-used between intercrate in non-intercrate + // mode, which could lead to using incorrect cache results. + let use_cache = !selcx.is_intercrate(); let projection_ty = infcx.resolve_vars_if_possible(projection_ty); let cache_key = ProjectionCacheKey::new(projection_ty); @@ -856,7 +850,11 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>( // bounds. It might be the case that we want two distinct caches, // or else another kind of cache entry. - let cache_result = infcx.inner.borrow_mut().projection_cache().try_start(cache_key); + let cache_result = if use_cache { + infcx.inner.borrow_mut().projection_cache().try_start(cache_key) + } else { + Ok(()) + }; match cache_result { Ok(()) => debug!("no cache"), Err(ProjectionCacheEntry::Ambiguous) => { @@ -881,7 +879,9 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>( // should ensure that, unless this happens within a snapshot that's // rolled back, fulfillment or evaluation will notice the cycle. - infcx.inner.borrow_mut().projection_cache().recur(cache_key); + if use_cache { + infcx.inner.borrow_mut().projection_cache().recur(cache_key); + } return Err(InProgress); } Err(ProjectionCacheEntry::Recur) => { @@ -963,20 +963,26 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>( .map_or(false, |res| res.must_apply_considering_regions()) }); - infcx.inner.borrow_mut().projection_cache().insert_ty(cache_key, result.clone()); + if use_cache { + infcx.inner.borrow_mut().projection_cache().insert_ty(cache_key, result.clone()); + } obligations.extend(result.obligations); Ok(Some(result.value)) } Ok(ProjectedTy::NoProgress(projected_ty)) => { debug!(?projected_ty, "opt_normalize_projection_type: no progress"); let result = Normalized { value: projected_ty, obligations: vec![] }; - infcx.inner.borrow_mut().projection_cache().insert_ty(cache_key, result.clone()); + if use_cache { + infcx.inner.borrow_mut().projection_cache().insert_ty(cache_key, result.clone()); + } // No need to extend `obligations`. Ok(Some(result.value)) } Err(ProjectionTyError::TooManyCandidates) => { debug!("opt_normalize_projection_type: too many candidates"); - infcx.inner.borrow_mut().projection_cache().ambiguous(cache_key); + if use_cache { + infcx.inner.borrow_mut().projection_cache().ambiguous(cache_key); + } Ok(None) } Err(ProjectionTyError::TraitSelectionError(_)) => { @@ -986,7 +992,9 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>( // Trait`, which when processed will cause the error to be // reported later - infcx.inner.borrow_mut().projection_cache().error(cache_key); + if use_cache { + infcx.inner.borrow_mut().projection_cache().error(cache_key); + } let result = normalize_to_error(selcx, param_env, projection_ty, cause, depth); obligations.extend(result.obligations); Ok(Some(result.value)) diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index b966779500b..50d6f82ae18 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -314,6 +314,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.infcx.tcx } + pub fn is_intercrate(&self) -> bool { + self.intercrate + } + /// Returns `true` if the trait predicate is considerd `const` to this selection context. pub fn is_trait_predicate_const(&self, pred: ty::TraitPredicate<'_>) -> bool { match pred.constness { @@ -1197,6 +1201,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { param_env: ty::ParamEnv<'tcx>, cache_fresh_trait_pred: ty::PolyTraitPredicate<'tcx>, ) -> Option<SelectionResult<'tcx, SelectionCandidate<'tcx>>> { + // 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(); let pred = &cache_fresh_trait_pred.skip_binder(); let trait_ref = pred.trait_ref; @@ -1233,6 +1244,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &self, result: &SelectionResult<'tcx, SelectionCandidate<'tcx>>, ) -> bool { + // 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 false; + } match result { Ok(Some(SelectionCandidate::ParamCandidate(trait_ref))) => !trait_ref.needs_infer(), _ => true, diff --git a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs index c8bcab6efd7..2ecc169e1cf 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs @@ -104,19 +104,21 @@ impl ChildrenExt for Children { let self_ty = trait_ref.self_ty(); // FIXME: should postpone string formatting until we decide to actually emit. - with_no_trimmed_paths(|| OverlapError { - with_impl: possible_sibling, - trait_desc: trait_ref.print_only_trait_path().to_string(), - // Only report the `Self` type if it has at least - // some outer concrete shell; otherwise, it's - // not adding much information. - self_desc: if self_ty.has_concrete_skeleton() { - Some(self_ty.to_string()) - } else { - None - }, - intercrate_ambiguity_causes: overlap.intercrate_ambiguity_causes, - involves_placeholder: overlap.involves_placeholder, + with_no_trimmed_paths(|| { + OverlapError { + with_impl: possible_sibling, + trait_desc: trait_ref.print_only_trait_path().to_string(), + // Only report the `Self` type if it has at least + // some outer concrete shell; otherwise, it's + // not adding much information. + self_desc: if self_ty.has_concrete_skeleton() { + Some(self_ty.to_string()) + } else { + None + }, + intercrate_ambiguity_causes: overlap.intercrate_ambiguity_causes, + involves_placeholder: overlap.involves_placeholder, + } }) }; diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 75307f13563..611ff26d652 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -209,7 +209,7 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>( _ => return, }; let fix_span = - |impl_item_ref: &hir::ImplItemRef<'_>| match tcx.hir().impl_item(impl_item_ref.id).kind { + |impl_item_ref: &hir::ImplItemRef| match tcx.hir().impl_item(impl_item_ref.id).kind { hir::ImplItemKind::Const(ty, _) | hir::ImplItemKind::TyAlias(ty) => ty.span, _ => impl_item_ref.span, }; diff --git a/compiler/rustc_traits/Cargo.toml b/compiler/rustc_traits/Cargo.toml index 219165ff550..2e56a1bf683 100644 --- a/compiler/rustc_traits/Cargo.toml +++ b/compiler/rustc_traits/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_traits" version = "0.0.0" -edition = "2018" +edition = "2021" [dependencies] tracing = "0.1" diff --git a/compiler/rustc_ty_utils/Cargo.toml b/compiler/rustc_ty_utils/Cargo.toml index 2eb27fb1ad6..78df95e680e 100644 --- a/compiler/rustc_ty_utils/Cargo.toml +++ b/compiler/rustc_ty_utils/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_ty_utils" version = "0.0.0" -edition = "2018" +edition = "2021" [dependencies] tracing = "0.1" diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 27ad7bf4c2d..3d3b2743700 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -100,7 +100,7 @@ fn associated_item_from_trait_item_ref( fn associated_item_from_impl_item_ref( tcx: TyCtxt<'_>, parent_def_id: LocalDefId, - impl_item_ref: &hir::ImplItemRef<'_>, + impl_item_ref: &hir::ImplItemRef, ) -> ty::AssocItem { let def_id = impl_item_ref.id.def_id; let (kind, has_self) = match impl_item_ref.kind { diff --git a/compiler/rustc_type_ir/Cargo.toml b/compiler/rustc_type_ir/Cargo.toml index 1f6acbe0d81..439e6cdf706 100644 --- a/compiler/rustc_type_ir/Cargo.toml +++ b/compiler/rustc_type_ir/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_type_ir" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] doctest = false diff --git a/compiler/rustc_typeck/Cargo.toml b/compiler/rustc_typeck/Cargo.toml index dd76a5e4b99..7e570e151c5 100644 --- a/compiler/rustc_typeck/Cargo.toml +++ b/compiler/rustc_typeck/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_typeck" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] test = false diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 2f2223ee822..33df541eb2b 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -2417,13 +2417,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let substs = InternalSubsts::for_item(tcx, def_id, |param, _| { if let Some(i) = (param.index as usize).checked_sub(generics.parent_count) { // Our own parameters are the resolved lifetimes. - match param.kind { - GenericParamDefKind::Lifetime - if let hir::GenericArg::Lifetime(lifetime) = &lifetimes[i] => - { + if let GenericParamDefKind::Lifetime = param.kind { + if let hir::GenericArg::Lifetime(lifetime) = &lifetimes[i] { self.ast_region_to_region(lifetime, None).into() + } else { + bug!() } - _ => bug!(), + } else { + bug!() } } else { match param.kind { diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 54e4eb47688..d6c59312c0b 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -906,7 +906,7 @@ pub(super) fn check_impl_items_against_trait<'tcx>( full_impl_span: Span, impl_id: LocalDefId, impl_trait_ref: ty::TraitRef<'tcx>, - impl_item_refs: &[hir::ImplItemRef<'_>], + impl_item_refs: &[hir::ImplItemRef], ) { // If the trait reference itself is erroneous (so the compilation is going // to fail), skip checking the items here -- the `impl_item` table in `tcx` diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs index 0acf1d26e25..da8b863e2db 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs @@ -484,8 +484,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { debug!("suggest_missing_return_type: return type {:?}", ty); debug!("suggest_missing_return_type: expected type {:?}", ty); let bound_vars = self.tcx.late_bound_vars(fn_id); - let ty = self.tcx.erase_late_bound_regions(Binder::bind_with_vars(ty, bound_vars)); + let ty = Binder::bind_with_vars(ty, bound_vars); let ty = self.normalize_associated_types_in(sp, ty); + let ty = self.tcx.erase_late_bound_regions(ty); if self.can_coerce(expected, ty) { err.span_label(sp, format!("expected `{}` because of return type", expected)); return true; diff --git a/compiler/rustc_typeck/src/check/generator_interior.rs b/compiler/rustc_typeck/src/check/generator_interior.rs index 3da9fd159a7..2910ce6de68 100644 --- a/compiler/rustc_typeck/src/check/generator_interior.rs +++ b/compiler/rustc_typeck/src/check/generator_interior.rs @@ -5,6 +5,7 @@ use super::FnCtxt; use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; +use rustc_errors::pluralize; use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def_id::DefId; @@ -12,9 +13,11 @@ use rustc_hir::hir_id::HirIdSet; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::{Arm, Expr, ExprKind, Guard, HirId, Pat, PatKind}; use rustc_middle::middle::region::{self, YieldData}; -use rustc_middle::ty::{self, Ty}; +use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_span::symbol::sym; use rustc_span::Span; use smallvec::SmallVec; +use tracing::debug; struct InteriorVisitor<'a, 'tcx> { fcx: &'a FnCtxt<'a, 'tcx>, @@ -30,12 +33,14 @@ struct InteriorVisitor<'a, 'tcx> { /// that they may succeed the said yield point in the post-order. guard_bindings: SmallVec<[SmallVec<[HirId; 4]>; 1]>, guard_bindings_set: HirIdSet, + linted_values: HirIdSet, } impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> { fn record( &mut self, ty: Ty<'tcx>, + hir_id: HirId, scope: Option<region::Scope>, expr: Option<&'tcx Expr<'tcx>>, source_span: Span, @@ -117,6 +122,23 @@ impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> { } else { // Insert the type into the ordered set. let scope_span = scope.map(|s| s.span(self.fcx.tcx, self.region_scope_tree)); + + if !self.linted_values.contains(&hir_id) { + check_must_not_suspend_ty( + self.fcx, + ty, + hir_id, + SuspendCheckData { + expr, + source_span, + yield_span: yield_data.span, + plural_len: 1, + ..Default::default() + }, + ); + self.linted_values.insert(hir_id); + } + self.types.insert(ty::GeneratorInteriorTypeCause { span: source_span, ty: &ty, @@ -163,6 +185,7 @@ pub fn resolve_interior<'a, 'tcx>( prev_unresolved_span: None, guard_bindings: <_>::default(), guard_bindings_set: <_>::default(), + linted_values: <_>::default(), }; intravisit::walk_body(&mut visitor, body); @@ -290,7 +313,7 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> { if let PatKind::Binding(..) = pat.kind { let scope = self.region_scope_tree.var_scope(pat.hir_id.local_id); let ty = self.fcx.typeck_results.borrow().pat_ty(pat); - self.record(ty, Some(scope), None, pat.span, false); + self.record(ty, pat.hir_id, Some(scope), None, pat.span, false); } } @@ -342,7 +365,14 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> { // If there are adjustments, then record the final type -- // this is the actual value that is being produced. if let Some(adjusted_ty) = self.fcx.typeck_results.borrow().expr_ty_adjusted_opt(expr) { - self.record(adjusted_ty, scope, Some(expr), expr.span, guard_borrowing_from_pattern); + self.record( + adjusted_ty, + expr.hir_id, + scope, + Some(expr), + expr.span, + guard_borrowing_from_pattern, + ); } // Also record the unadjusted type (which is the only type if @@ -380,9 +410,23 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> { tcx.mk_region(ty::RegionKind::ReErased), ty::TypeAndMut { ty, mutbl: hir::Mutability::Not }, ); - self.record(ref_ty, scope, Some(expr), expr.span, guard_borrowing_from_pattern); + self.record( + ref_ty, + expr.hir_id, + scope, + Some(expr), + expr.span, + guard_borrowing_from_pattern, + ); } - self.record(ty, scope, Some(expr), expr.span, guard_borrowing_from_pattern); + self.record( + ty, + expr.hir_id, + scope, + Some(expr), + expr.span, + guard_borrowing_from_pattern, + ); } else { self.fcx.tcx.sess.delay_span_bug(expr.span, "no type for node"); } @@ -409,3 +453,173 @@ impl<'a, 'tcx> Visitor<'tcx> for ArmPatCollector<'a> { } } } + +#[derive(Default)] +pub struct SuspendCheckData<'a, 'tcx> { + expr: Option<&'tcx Expr<'tcx>>, + source_span: Span, + yield_span: Span, + descr_pre: &'a str, + descr_post: &'a str, + plural_len: usize, +} + +// Returns whether it emitted a diagnostic or not +// Note that this fn and the proceding one are based on the code +// for creating must_use diagnostics +// +// Note that this technique was chosen over things like a `Suspend` marker trait +// as it is simpler and has precendent in the compiler +pub fn check_must_not_suspend_ty<'tcx>( + fcx: &FnCtxt<'_, 'tcx>, + ty: Ty<'tcx>, + hir_id: HirId, + data: SuspendCheckData<'_, 'tcx>, +) -> bool { + if ty.is_unit() + // FIXME: should this check `is_ty_uninhabited_from`. This query is not available in this stage + // of typeck (before ReVar and RePlaceholder are removed), but may remove noise, like in + // `must_use` + // || fcx.tcx.is_ty_uninhabited_from(fcx.tcx.parent_module(hir_id).to_def_id(), ty, fcx.param_env) + { + return false; + } + + let plural_suffix = pluralize!(data.plural_len); + + match *ty.kind() { + ty::Adt(..) if ty.is_box() => { + let boxed_ty = ty.boxed_ty(); + let descr_pre = &format!("{}boxed ", data.descr_pre); + check_must_not_suspend_ty(fcx, boxed_ty, hir_id, SuspendCheckData { descr_pre, ..data }) + } + ty::Adt(def, _) => check_must_not_suspend_def(fcx.tcx, def.did, hir_id, data), + // FIXME: support adding the attribute to TAITs + ty::Opaque(def, _) => { + let mut has_emitted = false; + for &(predicate, _) in fcx.tcx.explicit_item_bounds(def) { + // We only look at the `DefId`, so it is safe to skip the binder here. + if let ty::PredicateKind::Trait(ref poly_trait_predicate) = + predicate.kind().skip_binder() + { + let def_id = poly_trait_predicate.trait_ref.def_id; + let descr_pre = &format!("{}implementer{} of ", data.descr_pre, plural_suffix); + if check_must_not_suspend_def( + fcx.tcx, + def_id, + hir_id, + SuspendCheckData { descr_pre, ..data }, + ) { + has_emitted = true; + break; + } + } + } + has_emitted + } + ty::Dynamic(binder, _) => { + let mut has_emitted = false; + for predicate in binder.iter() { + if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder() { + let def_id = trait_ref.def_id; + let descr_post = &format!(" trait object{}{}", plural_suffix, data.descr_post); + if check_must_not_suspend_def( + fcx.tcx, + def_id, + hir_id, + SuspendCheckData { descr_post, ..data }, + ) { + has_emitted = true; + break; + } + } + } + has_emitted + } + ty::Tuple(ref tys) => { + let mut has_emitted = false; + let spans = if let Some(hir::ExprKind::Tup(comps)) = data.expr.map(|e| &e.kind) { + debug_assert_eq!(comps.len(), tys.len()); + comps.iter().map(|e| e.span).collect() + } else { + vec![] + }; + for (i, ty) in tys.iter().map(|k| k.expect_ty()).enumerate() { + let descr_post = &format!(" in tuple element {}", i); + let span = *spans.get(i).unwrap_or(&data.source_span); + if check_must_not_suspend_ty( + fcx, + ty, + hir_id, + SuspendCheckData { descr_post, source_span: span, ..data }, + ) { + has_emitted = true; + } + } + has_emitted + } + ty::Array(ty, len) => { + let descr_pre = &format!("{}array{} of ", data.descr_pre, plural_suffix); + check_must_not_suspend_ty( + fcx, + ty, + hir_id, + SuspendCheckData { + descr_pre, + plural_len: len.try_eval_usize(fcx.tcx, fcx.param_env).unwrap_or(0) as usize + + 1, + ..data + }, + ) + } + _ => false, + } +} + +fn check_must_not_suspend_def( + tcx: TyCtxt<'_>, + def_id: DefId, + hir_id: HirId, + data: SuspendCheckData<'_, '_>, +) -> bool { + for attr in tcx.get_attrs(def_id).iter() { + if attr.has_name(sym::must_not_suspend) { + tcx.struct_span_lint_hir( + rustc_session::lint::builtin::MUST_NOT_SUSPEND, + hir_id, + data.source_span, + |lint| { + let msg = format!( + "{}`{}`{} held across a suspend point, but should not be", + data.descr_pre, + tcx.def_path_str(def_id), + data.descr_post, + ); + let mut err = lint.build(&msg); + + // add span pointing to the offending yield/await + err.span_label(data.yield_span, "the value is held across this suspend point"); + + // Add optional reason note + if let Some(note) = attr.value_str() { + // FIXME(guswynn): consider formatting this better + err.span_note(data.source_span, ¬e.as_str()); + } + + // Add some quick suggestions on what to do + // FIXME: can `drop` work as a suggestion here as well? + err.span_help( + data.source_span, + "consider using a block (`{ ... }`) \ + to shrink the value's scope, ending before the suspend point", + ); + + err.emit(); + }, + ); + + return true; + } + } + false +} diff --git a/compiler/rustc_typeck/src/coherence/inherent_impls.rs b/compiler/rustc_typeck/src/coherence/inherent_impls.rs index c7be9e21235..f3fe09ac003 100644 --- a/compiler/rustc_typeck/src/coherence/inherent_impls.rs +++ b/compiler/rustc_typeck/src/coherence/inherent_impls.rs @@ -401,7 +401,7 @@ impl InherentCollect<'tcx> { lang: &str, ty: &str, span: Span, - assoc_items: &[hir::ImplItemRef<'_>], + assoc_items: &[hir::ImplItemRef], ) { match (lang_def_id, lang_def_id2) { (Some(lang_def_id), _) if lang_def_id == impl_def_id.to_def_id() => { diff --git a/compiler/rustc_typeck/src/impl_wf_check.rs b/compiler/rustc_typeck/src/impl_wf_check.rs index 9b23bf241cc..5d2f8fc4242 100644 --- a/compiler/rustc_typeck/src/impl_wf_check.rs +++ b/compiler/rustc_typeck/src/impl_wf_check.rs @@ -97,7 +97,7 @@ impl ItemLikeVisitor<'tcx> for ImplWfCheck<'tcx> { fn enforce_impl_params_are_constrained( tcx: TyCtxt<'_>, impl_def_id: LocalDefId, - impl_item_refs: &[hir::ImplItemRef<'_>], + impl_item_refs: &[hir::ImplItemRef], ) { // Every lifetime used in an associated type must be constrained. let impl_self_ty = tcx.type_of(impl_def_id); @@ -228,7 +228,7 @@ fn report_unused_parameter(tcx: TyCtxt<'_>, span: Span, kind: &str, name: &str) } /// Enforce that we do not have two items in an impl with the same name. -fn enforce_impl_items_are_distinct(tcx: TyCtxt<'_>, impl_item_refs: &[hir::ImplItemRef<'_>]) { +fn enforce_impl_items_are_distinct(tcx: TyCtxt<'_>, impl_item_refs: &[hir::ImplItemRef]) { let mut seen_type_items = FxHashMap::default(); let mut seen_value_items = FxHashMap::default(); for impl_item_ref in impl_item_refs { |
