diff --git a/Cargo.lock b/Cargo.lock index 75c7de4f405aa..78f3e22f95b3e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -119,6 +119,16 @@ dependencies = [ "yansi-term", ] +[[package]] +name = "annotate-snippets" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a433302f833baa830c0092100c481c7ea768c5981a3c36f549517a502f246dd" +dependencies = [ + "anstyle", + "unicode-width", +] + [[package]] name = "ansi_term" version = "0.12.1" @@ -3771,7 +3781,7 @@ dependencies = [ name = "rustc_errors" version = "0.0.0" dependencies = [ - "annotate-snippets", + "annotate-snippets 0.10.1", "derive_setters", "rustc_ast", "rustc_ast_pretty", @@ -3831,7 +3841,7 @@ dependencies = [ name = "rustc_fluent_macro" version = "0.0.0" dependencies = [ - "annotate-snippets", + "annotate-snippets 0.10.1", "fluent-bundle", "fluent-syntax", "proc-macro2", @@ -4738,7 +4748,7 @@ dependencies = [ name = "rustfmt-nightly" version = "1.7.0" dependencies = [ - "annotate-snippets", + "annotate-snippets 0.9.1", "anyhow", "bytecount", "cargo_metadata 0.15.4", @@ -5728,7 +5738,7 @@ version = "0.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aaf4bf7c184b8dfc7a4d3b90df789b1eb992ee42811cd115f32a7a1eb781058d" dependencies = [ - "annotate-snippets", + "annotate-snippets 0.9.1", "anyhow", "bstr", "cargo-platform", @@ -5859,9 +5869,9 @@ checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" [[package]] name = "unicode-width" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" +checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" dependencies = [ "compiler_builtins", "rustc-std-workspace-core", diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index e1e4e5fc56750..21077c312bdc8 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2873,6 +2873,7 @@ impl Item { | ItemKind::ForeignMod(_) | ItemKind::GlobalAsm(_) | ItemKind::MacCall(_) + | ItemKind::Delegation(_) | ItemKind::MacroDef(_) => None, ItemKind::Static(_) => None, ItemKind::Const(i) => Some(&i.generics), @@ -3019,6 +3020,15 @@ pub struct Fn { pub body: Option>, } +#[derive(Clone, Encodable, Decodable, Debug)] +pub struct Delegation { + /// Path resolution id. + pub id: NodeId, + pub qself: Option>, + pub path: Path, + pub body: Option>, +} + #[derive(Clone, Encodable, Decodable, Debug)] pub struct StaticItem { pub ty: P, @@ -3104,6 +3114,11 @@ pub enum ItemKind { /// A macro definition. MacroDef(MacroDef), + + /// A delegation item (`reuse`). + /// + /// E.g. `reuse ::name { target_expr_template }`. + Delegation(Box), } impl ItemKind { @@ -3111,7 +3126,8 @@ impl ItemKind { use ItemKind::*; match self { Use(..) | Static(..) | Const(..) | Fn(..) | Mod(..) | GlobalAsm(..) | TyAlias(..) - | Struct(..) | Union(..) | Trait(..) | TraitAlias(..) | MacroDef(..) => "a", + | Struct(..) | Union(..) | Trait(..) | TraitAlias(..) | MacroDef(..) + | Delegation(..) => "a", ExternCrate(..) | ForeignMod(..) | MacCall(..) | Enum(..) | Impl { .. } => "an", } } @@ -3135,6 +3151,7 @@ impl ItemKind { ItemKind::MacCall(..) => "item macro invocation", ItemKind::MacroDef(..) => "macro definition", ItemKind::Impl { .. } => "implementation", + ItemKind::Delegation(..) => "delegated function", } } @@ -3176,6 +3193,8 @@ pub enum AssocItemKind { Type(Box), /// A macro expanding to associated items. MacCall(P), + /// An associated delegation item. + Delegation(Box), } impl AssocItemKind { @@ -3184,7 +3203,7 @@ impl AssocItemKind { Self::Const(box ConstItem { defaultness, .. }) | Self::Fn(box Fn { defaultness, .. }) | Self::Type(box TyAlias { defaultness, .. }) => defaultness, - Self::MacCall(..) => Defaultness::Final, + Self::MacCall(..) | Self::Delegation(..) => Defaultness::Final, } } } @@ -3196,6 +3215,7 @@ impl From for ItemKind { AssocItemKind::Fn(fn_kind) => ItemKind::Fn(fn_kind), AssocItemKind::Type(ty_alias_kind) => ItemKind::TyAlias(ty_alias_kind), AssocItemKind::MacCall(a) => ItemKind::MacCall(a), + AssocItemKind::Delegation(delegation) => ItemKind::Delegation(delegation), } } } @@ -3209,6 +3229,7 @@ impl TryFrom for AssocItemKind { ItemKind::Fn(fn_kind) => AssocItemKind::Fn(fn_kind), ItemKind::TyAlias(ty_kind) => AssocItemKind::Type(ty_kind), ItemKind::MacCall(a) => AssocItemKind::MacCall(a), + ItemKind::Delegation(d) => AssocItemKind::Delegation(d), _ => return Err(item_kind), }) } diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 82f28143630d3..450555d0cb56d 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -1117,6 +1117,14 @@ pub fn noop_visit_item_kind(kind: &mut ItemKind, vis: &mut T) { } ItemKind::MacCall(m) => vis.visit_mac_call(m), ItemKind::MacroDef(def) => vis.visit_macro_def(def), + ItemKind::Delegation(box Delegation { id, qself, path, body }) => { + vis.visit_id(id); + vis.visit_qself(qself); + vis.visit_path(path); + if let Some(body) = body { + vis.visit_block(body); + } + } } } @@ -1155,6 +1163,14 @@ pub fn noop_flat_map_assoc_item( visit_opt(ty, |ty| visitor.visit_ty(ty)); } AssocItemKind::MacCall(mac) => visitor.visit_mac_call(mac), + AssocItemKind::Delegation(box Delegation { id, qself, path, body }) => { + visitor.visit_id(id); + visitor.visit_qself(qself); + visitor.visit_path(path); + if let Some(body) = body { + visitor.visit_block(body); + } + } } visitor.visit_span(span); visit_lazy_tts(tokens, visitor); diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 45261ca48fc25..3617df931e2a2 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -375,6 +375,15 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) { } ItemKind::MacCall(mac) => visitor.visit_mac_call(mac), ItemKind::MacroDef(ts) => visitor.visit_mac_def(ts, item.id), + ItemKind::Delegation(box Delegation { id: _, qself, path, body }) => { + if let Some(qself) = qself { + visitor.visit_ty(&qself.ty); + } + walk_path(visitor, path); + if let Some(body) = body { + visitor.visit_block(body); + } + } } walk_list!(visitor, visit_attribute, &item.attrs); } @@ -704,6 +713,15 @@ pub fn walk_assoc_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem, AssocItemKind::MacCall(mac) => { visitor.visit_mac_call(mac); } + AssocItemKind::Delegation(box Delegation { id: _, qself, path, body }) => { + if let Some(qself) = qself { + visitor.visit_ty(&qself.ty); + } + walk_path(visitor, path); + if let Some(body) = body { + visitor.visit_block(body); + } + } } } diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs new file mode 100644 index 0000000000000..6ccf39b0cb167 --- /dev/null +++ b/compiler/rustc_ast_lowering/src/delegation.rs @@ -0,0 +1,348 @@ +//! This module implements expansion of delegation items with early resolved paths. +//! It includes a delegation to a free functions: +//! +//! ```ignore (illustrative) +//! reuse module::name { target_expr_template } +//! ``` +//! +//! And delegation to a trait methods: +//! +//! ```ignore (illustrative) +//! reuse ::name { target_expr_template } +//! ``` +//! +//! After expansion for both cases we get: +//! +//! ```ignore (illustrative) +//! fn name( +//! arg0: InferDelegation(sig_id, Input(0)), +//! arg1: InferDelegation(sig_id, Input(1)), +//! ..., +//! argN: InferDelegation(sig_id, Input(N)), +//! ) -> InferDelegation(sig_id, Output) { +//! callee_path(target_expr_template(arg0), arg1, ..., argN) +//! } +//! ``` +//! +//! Where `callee_path` is a path in delegation item e.g. `::name`. +//! `sig_id` is a id of item from which the signature is inherited. It may be a delegation +//! item id (`item_id`) in case of impl trait or path resolution id (`path_id`) otherwise. +//! +//! Since we do not have a proper way to obtain function type information by path resolution +//! in AST, we mark each function parameter type as `InferDelegation` and inherit it in `AstConv`. +//! +//! Similarly generics, predicates and header are set to the "default" values. +//! In case of discrepancy with callee function the `NotSupportedDelegation` error will +//! also be emitted in `AstConv`. + +use crate::{ImplTraitPosition, ResolverAstLoweringExt}; + +use super::{ImplTraitContext, LoweringContext, ParamMode}; + +use ast::visit::Visitor; +use hir::def::{DefKind, PartialRes, Res}; +use hir::{BodyId, HirId}; +use rustc_ast as ast; +use rustc_ast::*; +use rustc_errors::ErrorGuaranteed; +use rustc_hir as hir; +use rustc_hir::def_id::DefId; +use rustc_middle::span_bug; +use rustc_middle::ty::ResolverAstLowering; +use rustc_span::{symbol::Ident, Span}; +use rustc_target::spec::abi; +use std::iter; + +pub(crate) struct DelegationResults<'hir> { + pub body_id: hir::BodyId, + pub sig: hir::FnSig<'hir>, + pub generics: &'hir hir::Generics<'hir>, +} + +impl<'hir> LoweringContext<'_, 'hir> { + pub(crate) fn delegation_has_self(&self, item_id: NodeId, path_id: NodeId, span: Span) -> bool { + let sig_id = self.get_delegation_sig_id(item_id, path_id, span); + let Ok(sig_id) = sig_id else { + return false; + }; + if let Some(local_sig_id) = sig_id.as_local() { + self.resolver.has_self.contains(&local_sig_id) + } else { + match self.tcx.def_kind(sig_id) { + DefKind::Fn => false, + DefKind::AssocFn => self.tcx.associated_item(sig_id).fn_has_self_parameter, + _ => span_bug!(span, "unexpected DefKind for delegation item"), + } + } + } + + pub(crate) fn lower_delegation( + &mut self, + delegation: &Delegation, + item_id: NodeId, + ) -> DelegationResults<'hir> { + let span = delegation.path.segments.last().unwrap().ident.span; + let sig_id = self.get_delegation_sig_id(item_id, delegation.id, span); + match sig_id { + Ok(sig_id) => { + let decl = self.lower_delegation_decl(sig_id, span); + let sig = self.lower_delegation_sig(span, decl); + let body_id = self.lower_delegation_body(sig.decl, delegation); + + let generics = self.lower_delegation_generics(span); + DelegationResults { body_id, sig, generics } + } + Err(err) => self.generate_delegation_error(err, span), + } + } + + fn get_delegation_sig_id( + &self, + item_id: NodeId, + path_id: NodeId, + span: Span, + ) -> Result { + let sig_id = if self.is_in_trait_impl { item_id } else { path_id }; + let sig_id = self + .resolver + .get_partial_res(sig_id) + .map(|r| r.expect_full_res().opt_def_id()) + .unwrap_or(None); + + sig_id.ok_or_else(|| { + self.tcx + .dcx() + .span_delayed_bug(span, "LoweringContext: couldn't resolve delegation item") + }) + } + + fn lower_delegation_generics(&mut self, span: Span) -> &'hir hir::Generics<'hir> { + self.arena.alloc(hir::Generics { + params: &[], + predicates: &[], + has_where_clause_predicates: false, + where_clause_span: span, + span: span, + }) + } + + fn lower_delegation_decl( + &mut self, + sig_id: DefId, + param_span: Span, + ) -> &'hir hir::FnDecl<'hir> { + let args_count = if let Some(local_sig_id) = sig_id.as_local() { + // Map may be filled incorrectly due to recursive delegation. + // Error will be emmited later in astconv. + self.resolver.fn_parameter_counts.get(&local_sig_id).cloned().unwrap_or_default() + } else { + self.tcx.fn_arg_names(sig_id).len() + }; + let inputs = self.arena.alloc_from_iter((0..args_count).into_iter().map(|arg| hir::Ty { + hir_id: self.next_id(), + kind: hir::TyKind::InferDelegation(sig_id, hir::InferDelegationKind::Input(arg)), + span: self.lower_span(param_span), + })); + + let output = self.arena.alloc(hir::Ty { + hir_id: self.next_id(), + kind: hir::TyKind::InferDelegation(sig_id, hir::InferDelegationKind::Output), + span: self.lower_span(param_span), + }); + + self.arena.alloc(hir::FnDecl { + inputs, + output: hir::FnRetTy::Return(output), + c_variadic: false, + lifetime_elision_allowed: true, + implicit_self: hir::ImplicitSelfKind::None, + }) + } + + fn lower_delegation_sig( + &mut self, + span: Span, + decl: &'hir hir::FnDecl<'hir>, + ) -> hir::FnSig<'hir> { + hir::FnSig { + decl, + header: hir::FnHeader { + unsafety: hir::Unsafety::Normal, + constness: hir::Constness::NotConst, + asyncness: hir::IsAsync::NotAsync, + abi: abi::Abi::Rust, + }, + span: self.lower_span(span), + } + } + + fn generate_param(&mut self, ty: &'hir hir::Ty<'hir>) -> (hir::Param<'hir>, NodeId) { + let pat_node_id = self.next_node_id(); + let pat_id = self.lower_node_id(pat_node_id); + let pat = self.arena.alloc(hir::Pat { + hir_id: pat_id, + kind: hir::PatKind::Binding(hir::BindingAnnotation::NONE, pat_id, Ident::empty(), None), + span: ty.span, + default_binding_modes: false, + }); + + (hir::Param { hir_id: self.next_id(), pat, ty_span: ty.span, span: ty.span }, pat_node_id) + } + + fn generate_arg(&mut self, ty: &'hir hir::Ty<'hir>, param_id: HirId) -> hir::Expr<'hir> { + let segments = self.arena.alloc_from_iter(iter::once(hir::PathSegment { + ident: Ident::empty(), + hir_id: self.next_id(), + res: Res::Local(param_id), + args: None, + infer_args: false, + })); + + let path = + self.arena.alloc(hir::Path { span: ty.span, res: Res::Local(param_id), segments }); + + hir::Expr { + hir_id: self.next_id(), + kind: hir::ExprKind::Path(hir::QPath::Resolved(None, path)), + span: ty.span, + } + } + + fn lower_delegation_body( + &mut self, + decl: &'hir hir::FnDecl<'hir>, + delegation: &Delegation, + ) -> BodyId { + let path = self.lower_qpath( + delegation.id, + &delegation.qself, + &delegation.path, + ParamMode::Optional, + &ImplTraitContext::Disallowed(ImplTraitPosition::Path), + None, + ); + let block = delegation.body.as_deref(); + + self.lower_body(|this| { + let mut parameters: Vec> = Vec::new(); + let mut args: Vec> = Vec::new(); + + for (idx, param_ty) in decl.inputs.iter().enumerate() { + let (param, pat_node_id) = this.generate_param(param_ty); + parameters.push(param); + + let arg = if let Some(block) = block + && idx == 0 + { + let mut self_resolver = SelfResolver { + resolver: this.resolver, + path_id: delegation.id, + self_param_id: pat_node_id, + }; + self_resolver.visit_block(block); + let block = this.lower_block(block, false); + hir::Expr { + hir_id: this.next_id(), + kind: hir::ExprKind::Block(block, None), + span: block.span, + } + } else { + let pat_hir_id = this.lower_node_id(pat_node_id); + this.generate_arg(param_ty, pat_hir_id) + }; + args.push(arg); + } + + let args = self.arena.alloc_from_iter(args); + let final_expr = this.generate_call(path, args); + (this.arena.alloc_from_iter(parameters), final_expr) + }) + } + + fn generate_call( + &mut self, + path: hir::QPath<'hir>, + args: &'hir [hir::Expr<'hir>], + ) -> hir::Expr<'hir> { + let callee = self.arena.alloc(hir::Expr { + hir_id: self.next_id(), + kind: hir::ExprKind::Path(path), + span: path.span(), + }); + + let expr = self.arena.alloc(hir::Expr { + hir_id: self.next_id(), + kind: hir::ExprKind::Call(callee, args), + span: path.span(), + }); + + let block = self.arena.alloc(hir::Block { + stmts: &[], + expr: Some(expr), + hir_id: self.next_id(), + rules: hir::BlockCheckMode::DefaultBlock, + span: path.span(), + targeted_by_break: false, + }); + + hir::Expr { + hir_id: self.next_id(), + kind: hir::ExprKind::Block(block, None), + span: path.span(), + } + } + + fn generate_delegation_error( + &mut self, + err: ErrorGuaranteed, + span: Span, + ) -> DelegationResults<'hir> { + let generics = self.lower_delegation_generics(span); + + let decl = self.arena.alloc(hir::FnDecl { + inputs: &[], + output: hir::FnRetTy::DefaultReturn(span), + c_variadic: false, + lifetime_elision_allowed: true, + implicit_self: hir::ImplicitSelfKind::None, + }); + + let sig = self.lower_delegation_sig(span, decl); + let body_id = self.lower_body(|this| { + let expr = + hir::Expr { hir_id: this.next_id(), kind: hir::ExprKind::Err(err), span: span }; + (&[], expr) + }); + DelegationResults { generics, body_id, sig } + } +} + +struct SelfResolver<'a> { + resolver: &'a mut ResolverAstLowering, + path_id: NodeId, + self_param_id: NodeId, +} + +impl<'a> SelfResolver<'a> { + fn try_replace_id(&mut self, id: NodeId) { + if let Some(res) = self.resolver.partial_res_map.get(&id) + && let Some(Res::Local(sig_id)) = res.full_res() + && sig_id == self.path_id + { + let new_res = PartialRes::new(Res::Local(self.self_param_id)); + self.resolver.partial_res_map.insert(id, new_res); + } + } +} + +impl<'ast, 'a> Visitor<'ast> for SelfResolver<'a> { + fn visit_path(&mut self, path: &'ast Path, id: NodeId) { + self.try_replace_id(id); + visit::walk_path(self, path); + } + + fn visit_path_segment(&mut self, seg: &'ast PathSegment) { + self.try_replace_id(seg.id); + visit::walk_path_segment(self, seg); + } +} diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index d8de447e5b4cd..a3ff02f5f6954 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -441,6 +441,14 @@ impl<'hir> LoweringContext<'_, 'hir> { let macro_def = self.arena.alloc(ast::MacroDef { body, macro_rules: *macro_rules }); hir::ItemKind::Macro(macro_def, macro_kind) } + ItemKind::Delegation(box delegation) => { + let delegation_results = self.lower_delegation(delegation, id); + hir::ItemKind::Fn( + delegation_results.sig, + delegation_results.generics, + delegation_results.body_id, + ) + } ItemKind::MacCall(..) => { panic!("`TyMac` should have been expanded by now") } @@ -805,6 +813,14 @@ impl<'hir> LoweringContext<'_, 'hir> { ); (generics, kind, ty.is_some()) } + AssocItemKind::Delegation(box delegation) => { + let delegation_results = self.lower_delegation(delegation, i.id); + let item_kind = hir::TraitItemKind::Fn( + delegation_results.sig, + hir::TraitFn::Provided(delegation_results.body_id), + ); + (delegation_results.generics, item_kind, true) + } AssocItemKind::MacCall(..) => panic!("macro item shouldn't exist at this point"), }; @@ -826,6 +842,9 @@ impl<'hir> LoweringContext<'_, 'hir> { AssocItemKind::Fn(box Fn { sig, .. }) => { hir::AssocItemKind::Fn { has_self: sig.decl.has_self() } } + AssocItemKind::Delegation(box delegation) => hir::AssocItemKind::Fn { + has_self: self.delegation_has_self(i.id, delegation.id, i.span), + }, AssocItemKind::MacCall(..) => unimplemented!(), }; let id = hir::TraitItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } }; @@ -908,6 +927,13 @@ impl<'hir> LoweringContext<'_, 'hir> { }, ) } + AssocItemKind::Delegation(box delegation) => { + let delegation_results = self.lower_delegation(delegation, i.id); + ( + delegation_results.generics, + hir::ImplItemKind::Fn(delegation_results.sig, delegation_results.body_id), + ) + } AssocItemKind::MacCall(..) => panic!("`TyMac` should have been expanded by now"), }; @@ -924,6 +950,13 @@ impl<'hir> LoweringContext<'_, 'hir> { } fn lower_impl_item_ref(&mut self, i: &AssocItem) -> hir::ImplItemRef { + let trait_item_def_id = self + .resolver + .get_partial_res(i.id) + .map(|r| r.expect_full_res().opt_def_id()) + .unwrap_or(None); + self.is_in_trait_impl = trait_item_def_id.is_some(); + hir::ImplItemRef { id: hir::ImplItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } }, ident: self.lower_ident(i.ident), @@ -934,12 +967,12 @@ impl<'hir> LoweringContext<'_, 'hir> { AssocItemKind::Fn(box Fn { sig, .. }) => { hir::AssocItemKind::Fn { has_self: sig.decl.has_self() } } + AssocItemKind::Delegation(box delegation) => hir::AssocItemKind::Fn { + has_self: self.delegation_has_self(i.id, delegation.id, i.span), + }, AssocItemKind::MacCall(..) => unimplemented!(), }, - trait_item_def_id: self - .resolver - .get_partial_res(i.id) - .map(|r| r.expect_full_res().def_id()), + trait_item_def_id, } } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index dc23b1dce7bf5..d2d42a15808ba 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -77,6 +77,7 @@ macro_rules! arena_vec { mod asm; mod block; +mod delegation; mod errors; mod expr; mod format; diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 737e81eb6ecc0..539b520f54f4e 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -556,6 +556,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { gate_all!(explicit_tail_calls, "`become` expression is experimental"); gate_all!(generic_const_items, "generic const items are experimental"); gate_all!(unnamed_fields, "unnamed fields are not yet fully implemented"); + gate_all!(fn_delegation, "functions delegation is not yet fully implemented"); if !visitor.features.never_patterns { if let Some(spans) = spans.get(&sym::never_patterns) { diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs index 43561a1c0209c..584f01e16c2c3 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs @@ -376,6 +376,9 @@ impl<'a> State<'a> { state.print_visibility(&item.vis) }); } + ast::ItemKind::Delegation(box delegation) => { + self.print_delegation(delegation, &item.vis, &item.attrs) + } } self.ann.post(self, AnnNode::Item(item)) } @@ -554,10 +557,38 @@ impl<'a> State<'a> { self.word(";"); } } + ast::AssocItemKind::Delegation(box delegation) => { + self.print_delegation(delegation, vis, &item.attrs) + } } self.ann.post(self, AnnNode::SubItem(id)) } + pub(crate) fn print_delegation( + &mut self, + delegation: &ast::Delegation, + vis: &ast::Visibility, + attrs: &[ast::Attribute], + ) { + if delegation.body.is_some() { + self.head(""); + } + self.print_visibility(vis); + self.word_space("reuse"); + + if let Some(qself) = &delegation.qself { + self.print_qpath(&delegation.path, qself, false); + } else { + self.print_path(&delegation.path, false, 0); + } + if let Some(body) = &delegation.body { + self.nbsp(); + self.print_block_with_attrs(body, attrs); + } else { + self.word(";"); + } + } + fn print_fn_full( &mut self, sig: &ast::FnSig, diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 495b255583c2a..0457b4e6ddc78 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -2399,10 +2399,10 @@ mod error { /// and we want only the best of those errors. /// /// The `report_use_of_moved_or_uninitialized` function checks this map and replaces the - /// diagnostic (if there is one) if the `Place` of the error being reported is a prefix of the - /// `Place` of the previous most diagnostic. This happens instead of buffering the error. Once - /// all move errors have been reported, any diagnostics in this map are added to the buffer - /// to be emitted. + /// diagnostic (if there is one) if the `Place` of the error being reported is a prefix of + /// the `Place` of the previous most diagnostic. This happens instead of buffering the + /// error. Once all move errors have been reported, any diagnostics in this map are added + /// to the buffer to be emitted. /// /// `BTreeMap` is used to preserve the order of insertions when iterating. This is necessary /// when errors in the map are being re-added to the error buffer so that errors with the @@ -2410,7 +2410,8 @@ mod error { buffered_move_errors: BTreeMap, (PlaceRef<'tcx>, DiagnosticBuilder<'tcx>)>, buffered_mut_errors: FxIndexMap, usize)>, - /// Diagnostics to be reported buffer. + /// Buffer of diagnostics to be reported. Uses `Diagnostic` rather than `DiagnosticBuilder` + /// because it has a mixture of error diagnostics and non-error diagnostics. buffered: Vec, /// Set to Some if we emit an error during borrowck tainted_by_errors: Option, @@ -2434,11 +2435,11 @@ mod error { "diagnostic buffered but not emitted", )) } - t.buffer(&mut self.buffered); + self.buffered.push(t.into_diagnostic()); } pub fn buffer_non_error_diag(&mut self, t: DiagnosticBuilder<'_, ()>) { - t.buffer(&mut self.buffered); + self.buffered.push(t.into_diagnostic()); } pub fn set_tainted_by_errors(&mut self, e: ErrorGuaranteed) { @@ -2486,13 +2487,13 @@ mod error { // Buffer any move errors that we collected and de-duplicated. for (_, (_, diag)) in std::mem::take(&mut self.errors.buffered_move_errors) { // We have already set tainted for this error, so just buffer it. - diag.buffer(&mut self.errors.buffered); + self.errors.buffered.push(diag.into_diagnostic()); } for (_, (mut diag, count)) in std::mem::take(&mut self.errors.buffered_mut_errors) { if count > 10 { diag.note(format!("...and {} other attempted mutable borrows", count - 10)); } - diag.buffer(&mut self.errors.buffered); + self.errors.buffered.push(diag.into_diagnostic()); } if !self.errors.buffered.is_empty() { diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs index 7ad2d03a5edd5..017843c7e7d15 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs @@ -1,4 +1,4 @@ -use rustc_middle::mir::coverage::{CounterId, CovTerm, ExpressionId}; +use rustc_middle::mir::coverage::{CodeRegion, CounterId, CovTerm, ExpressionId, MappingKind}; /// Must match the layout of `LLVMRustCounterKind`. #[derive(Copy, Clone, Debug)] @@ -149,6 +149,24 @@ pub struct CounterMappingRegion { } impl CounterMappingRegion { + pub(crate) fn from_mapping( + mapping_kind: &MappingKind, + local_file_id: u32, + code_region: &CodeRegion, + ) -> Self { + let &CodeRegion { file_name: _, start_line, start_col, end_line, end_col } = code_region; + match *mapping_kind { + MappingKind::Code(term) => Self::code_region( + Counter::from_term(term), + local_file_id, + start_line, + start_col, + end_line, + end_col, + ), + } + } + pub(crate) fn code_region( counter: Counter, file_id: u32, diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs index cd67fafb8e4e2..d85d9411f03b6 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs @@ -4,7 +4,8 @@ use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxIndexSet; use rustc_index::bit_set::BitSet; use rustc_middle::mir::coverage::{ - CodeRegion, CounterId, CovTerm, Expression, ExpressionId, FunctionCoverageInfo, Mapping, Op, + CodeRegion, CounterId, CovTerm, Expression, ExpressionId, FunctionCoverageInfo, Mapping, + MappingKind, Op, }; use rustc_middle::ty::Instance; use rustc_span::Symbol; @@ -64,8 +65,8 @@ impl<'tcx> FunctionCoverageCollector<'tcx> { // For each expression ID that is directly used by one or more mappings, // mark it as not-yet-seen. This indicates that we expect to see a // corresponding `ExpressionUsed` statement during MIR traversal. - for Mapping { term, .. } in &function_coverage_info.mappings { - if let &CovTerm::Expression(id) = term { + for term in function_coverage_info.mappings.iter().flat_map(|m| m.kind.terms()) { + if let CovTerm::Expression(id) = term { expressions_seen.remove(id); } } @@ -221,20 +222,21 @@ impl<'tcx> FunctionCoverage<'tcx> { /// that will be used by `mapgen` when preparing for FFI. pub(crate) fn counter_regions( &self, - ) -> impl Iterator + ExactSizeIterator { + ) -> impl Iterator + ExactSizeIterator { self.function_coverage_info.mappings.iter().map(move |mapping| { - let &Mapping { term, ref code_region } = mapping; - let counter = self.counter_for_term(term); - (counter, code_region) + let Mapping { kind, code_region } = mapping; + let kind = + kind.map_terms(|term| if self.is_zero_term(term) { CovTerm::Zero } else { term }); + (kind, code_region) }) } fn counter_for_term(&self, term: CovTerm) -> Counter { - if is_zero_term(&self.counters_seen, &self.zero_expressions, term) { - Counter::ZERO - } else { - Counter::from_term(term) - } + if self.is_zero_term(term) { Counter::ZERO } else { Counter::from_term(term) } + } + + fn is_zero_term(&self, term: CovTerm) -> bool { + is_zero_term(&self.counters_seen, &self.zero_expressions, term) } } diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index 51df14df644e0..6116a6fd222b3 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -12,7 +12,6 @@ use rustc_hir::def_id::DefId; use rustc_index::IndexVec; use rustc_middle::bug; use rustc_middle::mir; -use rustc_middle::mir::coverage::CodeRegion; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::def_id::DefIdSet; use rustc_span::Symbol; @@ -237,7 +236,7 @@ fn encode_mappings_for_function( // Prepare file IDs for each filename, and prepare the mapping data so that // we can pass it through FFI to LLVM. for (file_name, counter_regions_for_file) in - &counter_regions.group_by(|(_counter, region)| region.file_name) + &counter_regions.group_by(|(_, region)| region.file_name) { // Look up the global file ID for this filename. let global_file_id = global_file_table.global_file_id_for_file_name(file_name); @@ -248,17 +247,12 @@ fn encode_mappings_for_function( // For each counter/region pair in this function+file, convert it to a // form suitable for FFI. - for (counter, region) in counter_regions_for_file { - let CodeRegion { file_name: _, start_line, start_col, end_line, end_col } = *region; - - debug!("Adding counter {counter:?} to map for {region:?}"); - mapping_regions.push(CounterMappingRegion::code_region( - counter, + for (mapping_kind, region) in counter_regions_for_file { + debug!("Adding counter {mapping_kind:?} to map for {region:?}"); + mapping_regions.push(CounterMappingRegion::from_mapping( + &mapping_kind, local_file_id.as_u32(), - start_line, - start_col, - end_line, - end_col, + region, )); } } diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index 738c532964a2c..ae9595d7e6444 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -1,6 +1,6 @@ //! The `Visitor` responsible for actually checking a `mir::Body` for invalid operations. -use rustc_errors::{Diagnostic, ErrorGuaranteed}; +use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_index::bit_set::BitSet; @@ -214,7 +214,7 @@ pub struct Checker<'mir, 'tcx> { local_has_storage_dead: Option>, error_emitted: Option, - secondary_errors: Vec, + secondary_errors: Vec>, } impl<'mir, 'tcx> Deref for Checker<'mir, 'tcx> { @@ -272,14 +272,17 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> { } // If we got through const-checking without emitting any "primary" errors, emit any - // "secondary" errors if they occurred. + // "secondary" errors if they occurred. Otherwise, cancel the "secondary" errors. let secondary_errors = mem::take(&mut self.secondary_errors); if self.error_emitted.is_none() { for error in secondary_errors { - self.tcx.dcx().emit_diagnostic(error); + error.emit(); } } else { assert!(self.tcx.dcx().has_errors().is_some()); + for error in secondary_errors { + error.cancel(); + } } } @@ -347,7 +350,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> { self.error_emitted = Some(reported); } - ops::DiagnosticImportance::Secondary => err.buffer(&mut self.secondary_errors), + ops::DiagnosticImportance::Secondary => self.secondary_errors.push(err), } } diff --git a/compiler/rustc_errors/Cargo.toml b/compiler/rustc_errors/Cargo.toml index fc3ff835a8136..0c1fcecb57173 100644 --- a/compiler/rustc_errors/Cargo.toml +++ b/compiler/rustc_errors/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start -annotate-snippets = "0.9" +annotate-snippets = "0.10" derive_setters = "0.1.6" rustc_ast = { path = "../rustc_ast" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs index 97f2efa7874d1..980ac31011931 100644 --- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs +++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs @@ -12,8 +12,7 @@ use crate::{ CodeSuggestion, Diagnostic, DiagnosticId, DiagnosticMessage, Emitter, FluentBundle, LazyFallbackBundle, Level, MultiSpan, Style, SubDiagnostic, }; -use annotate_snippets::display_list::{DisplayList, FormatOptions}; -use annotate_snippets::snippet::*; +use annotate_snippets::{Annotation, AnnotationType, Renderer, Slice, Snippet, SourceAnnotation}; use rustc_data_structures::sync::Lrc; use rustc_error_messages::FluentArgs; use rustc_span::source_map::SourceMap; @@ -190,11 +189,6 @@ impl AnnotateSnippetEmitter { annotation_type: annotation_type_for_level(*level), }), footer: vec![], - opt: FormatOptions { - color: true, - anonymized_line_numbers: self.ui_testing, - margin: None, - }, slices: annotated_files .iter() .map(|(file_name, source, line_index, annotations)| { @@ -222,7 +216,8 @@ impl AnnotateSnippetEmitter { // FIXME(#59346): Figure out if we can _always_ print to stderr or not. // `emitter.rs` has the `Destination` enum that lists various possible output // destinations. - eprintln!("{}", DisplayList::from(snippet)) + let renderer = Renderer::plain().anonymized_line_numbers(self.ui_testing); + eprintln!("{}", renderer.render(snippet)) } // FIXME(#59346): Is it ok to return None if there's no source_map? } diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index a02909f29c45d..bd7c58d904e70 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -255,35 +255,13 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { /// Stashes diagnostic for possible later improvement in a different, /// later stage of the compiler. The diagnostic can be accessed with /// the provided `span` and `key` through [`DiagCtxt::steal_diagnostic()`]. - /// - /// As with `buffer`, this is unless the dcx has disabled such buffering. pub fn stash(self, span: Span, key: StashKey) { - if let Some((diag, dcx)) = self.into_diagnostic() { - dcx.stash_diagnostic(span, key, diag); - } - } - - /// Converts the builder to a `Diagnostic` for later emission, - /// unless dcx has disabled such buffering. - fn into_diagnostic(mut self) -> Option<(Diagnostic, &'a DiagCtxt)> { - if self.dcx.inner.lock().flags.treat_err_as_bug.is_some() { - self.emit(); - return None; - } - - let diag = self.take_diag(); - - // Logging here is useful to help track down where in logs an error was - // actually emitted. - debug!("buffer: diag={:?}", diag); - - Some((diag, self.dcx)) + self.dcx.stash_diagnostic(span, key, self.into_diagnostic()); } - /// Buffers the diagnostic for later emission, - /// unless dcx has disabled such buffering. - pub fn buffer(self, buffered_diagnostics: &mut Vec) { - buffered_diagnostics.extend(self.into_diagnostic().map(|(diag, _)| diag)); + /// Converts the builder to a `Diagnostic` for later emission. + pub fn into_diagnostic(mut self) -> Diagnostic { + self.take_diag() } /// Delay emission of this diagnostic as a bug. diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 8fb539fc3582f..404c89ea01b64 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -981,6 +981,10 @@ impl DiagCtxt { inner.emit_stashed_diagnostics(); + if inner.treat_err_as_bug() { + return; + } + let warnings = match inner.deduplicated_warn_count { 0 => Cow::from(""), 1 => Cow::from("1 warning emitted"), @@ -991,9 +995,6 @@ impl DiagCtxt { 1 => Cow::from("aborting due to 1 previous error"), count => Cow::from(format!("aborting due to {count} previous errors")), }; - if inner.treat_err_as_bug() { - return; - } match (errors.len(), warnings.len()) { (0, 0) => return, @@ -1168,7 +1169,8 @@ impl DiagCtxt { let mut inner = self.inner.borrow_mut(); if loud && lint_level.is_error() { - inner.bump_err_count(); + inner.err_count += 1; + inner.panic_if_treat_err_as_bug(); } inner.emitter.emit_unused_externs(lint_level, unused_externs) @@ -1255,7 +1257,7 @@ impl DiagCtxtInner { } fn emit_diagnostic(&mut self, mut diagnostic: Diagnostic) -> Option { - if matches!(diagnostic.level, Error | Fatal) && self.treat_err_as_bug() { + if matches!(diagnostic.level, Error | Fatal) && self.treat_next_err_as_bug() { diagnostic.level = Bug; } @@ -1353,10 +1355,11 @@ impl DiagCtxtInner { } if diagnostic.is_error() { if diagnostic.is_lint { - self.bump_lint_err_count(); + self.lint_err_count += 1; } else { - self.bump_err_count(); + self.err_count += 1; } + self.panic_if_treat_err_as_bug(); #[allow(deprecated)] { @@ -1447,16 +1450,6 @@ impl DiagCtxtInner { panic::panic_any(DelayedBugPanic); } - fn bump_lint_err_count(&mut self) { - self.lint_err_count += 1; - self.panic_if_treat_err_as_bug(); - } - - fn bump_err_count(&mut self) { - self.err_count += 1; - self.panic_if_treat_err_as_bug(); - } - fn panic_if_treat_err_as_bug(&self) { if self.treat_err_as_bug() { match ( diff --git a/compiler/rustc_errors/src/markdown/tests/term.rs b/compiler/rustc_errors/src/markdown/tests/term.rs index a0d956bf0cdab..bab47dcc175f1 100644 --- a/compiler/rustc_errors/src/markdown/tests/term.rs +++ b/compiler/rustc_errors/src/markdown/tests/term.rs @@ -5,7 +5,8 @@ use termcolor::{BufferWriter, ColorChoice}; use super::*; const INPUT: &str = include_str!("input.md"); -const OUTPUT_PATH: &[&str] = &[env!("CARGO_MANIFEST_DIR"), "src","markdown","tests","output.stdout"]; +const OUTPUT_PATH: &[&str] = + &[env!("CARGO_MANIFEST_DIR"), "src", "markdown", "tests", "output.stdout"]; const TEST_WIDTH: usize = 80; @@ -34,7 +35,7 @@ quis dolor non venenatis. Aliquam ut. "; fn test_wrapping_write() { WIDTH.with(|w| w.set(TEST_WIDTH)); let mut buf = BufWriter::new(Vec::new()); - let txt = TXT.replace("-\n","-").replace("_\n","_").replace('\n', " ").replace(" ", ""); + let txt = TXT.replace("-\n", "-").replace("_\n", "_").replace('\n', " ").replace(" ", ""); write_wrapping(&mut buf, &txt, 0, None).unwrap(); write_wrapping(&mut buf, &txt, 4, None).unwrap(); write_wrapping( diff --git a/compiler/rustc_fluent_macro/Cargo.toml b/compiler/rustc_fluent_macro/Cargo.toml index 872dd29a7a8ac..c5a53ae831355 100644 --- a/compiler/rustc_fluent_macro/Cargo.toml +++ b/compiler/rustc_fluent_macro/Cargo.toml @@ -8,7 +8,7 @@ proc-macro = true [dependencies] # tidy-alphabetical-start -annotate-snippets = "0.9" +annotate-snippets = "0.10" fluent-bundle = "0.15.2" fluent-syntax = "0.11" proc-macro2 = "1" diff --git a/compiler/rustc_fluent_macro/src/fluent.rs b/compiler/rustc_fluent_macro/src/fluent.rs index 3b1b63455eddd..520a64aaf5e23 100644 --- a/compiler/rustc_fluent_macro/src/fluent.rs +++ b/compiler/rustc_fluent_macro/src/fluent.rs @@ -1,7 +1,4 @@ -use annotate_snippets::{ - display_list::DisplayList, - snippet::{Annotation, AnnotationType, Slice, Snippet, SourceAnnotation}, -}; +use annotate_snippets::{Annotation, AnnotationType, Renderer, Slice, Snippet, SourceAnnotation}; use fluent_bundle::{FluentBundle, FluentError, FluentResource}; use fluent_syntax::{ ast::{ @@ -179,10 +176,9 @@ pub(crate) fn fluent_messages(input: proc_macro::TokenStream) -> proc_macro::Tok range: (pos.start, pos.end - 1), }], }], - opt: Default::default(), }; - let dl = DisplayList::from(snippet); - eprintln!("{dl}\n"); + let renderer = Renderer::plain(); + eprintln!("{}\n", renderer.render(snippet)); } return failed(&crate_name); diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 58ac9668da5e9..6b347f7035a3b 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2571,9 +2571,17 @@ pub enum OpaqueTyOrigin { }, } +#[derive(Debug, Clone, Copy, PartialEq, Eq, HashStable_Generic)] +pub enum InferDelegationKind { + Input(usize), + Output, +} + /// The various kinds of types recognized by the compiler. #[derive(Debug, Clone, Copy, HashStable_Generic)] pub enum TyKind<'hir> { + /// Actual type should be inherited from `DefId` signature + InferDelegation(DefId, InferDelegationKind), /// A variable length slice (i.e., `[T]`). Slice(&'hir Ty<'hir>), /// A fixed length array (i.e., `[T; n]`). diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index dd3633b6b4f74..adc090258093a 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -856,7 +856,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) { visitor.visit_lifetime(lifetime); } TyKind::Typeof(ref expression) => visitor.visit_anon_const(expression), - TyKind::Infer | TyKind::Err(_) => {} + TyKind::Infer | TyKind::InferDelegation(..) | TyKind::Err(_) => {} } } diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 6a17668ad17f8..432c9c12cbfbc 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -263,6 +263,10 @@ hir_analysis_must_implement_not_function_span_note = required by this annotation hir_analysis_must_implement_one_of_attribute = the `#[rustc_must_implement_one_of]` attribute must be used with at least 2 args +hir_analysis_not_supported_delegation = + {$descr} is not supported yet + .label = callee defined here + hir_analysis_only_current_traits_arbitrary = only traits defined in the current crate can be implemented for arbitrary types hir_analysis_only_current_traits_foreign = this is not defined in the current crate because this is a foreign trait diff --git a/compiler/rustc_hir_analysis/src/astconv/bounds.rs b/compiler/rustc_hir_analysis/src/astconv/bounds.rs index 1f88aaa6a4b01..2ad96a2489124 100644 --- a/compiler/rustc_hir_analysis/src/astconv/bounds.rs +++ b/compiler/rustc_hir_analysis/src/astconv/bounds.rs @@ -300,13 +300,15 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { .expect("missing associated item"); if !assoc_item.visibility(tcx).is_accessible_from(def_scope, tcx) { - tcx.dcx() + let reported = tcx + .dcx() .struct_span_err( binding.span, format!("{} `{}` is private", assoc_item.kind, binding.item_name), ) .with_span_label(binding.span, format!("private {}", assoc_item.kind)) .emit(); + self.set_tainted_by_errors(reported); } tcx.check_stability(assoc_item.def_id, Some(hir_ref_id), binding.span, None); diff --git a/compiler/rustc_hir_analysis/src/astconv/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs index fc2ed104b3dc8..7b23b74f82920 100644 --- a/compiler/rustc_hir_analysis/src/astconv/errors.rs +++ b/compiler/rustc_hir_analysis/src/astconv/errors.rs @@ -354,7 +354,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ); err.span_label(name.span, format!("multiple `{name}` found")); self.note_ambiguous_inherent_assoc_type(&mut err, candidates, span); - err.emit() + let reported = err.emit(); + self.set_tainted_by_errors(reported); + reported } // FIXME(fmease): Heavily adapted from `rustc_hir_typeck::method::suggest`. Deduplicate. @@ -843,7 +845,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } } - err.emit(); + self.set_tainted_by_errors(err.emit()); } } diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 1f47564649eda..78740ac33ca09 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -29,10 +29,9 @@ use rustc_hir::{GenericArg, GenericArgs, OpaqueTyOrigin}; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::ObligationCause; use rustc_middle::middle::stability::AllowUnstable; -use rustc_middle::ty::GenericParamDefKind; use rustc_middle::ty::{ - self, Const, GenericArgKind, GenericArgsRef, IsSuggestable, ParamEnv, Ty, TyCtxt, - TypeVisitableExt, + self, Const, GenericArgKind, GenericArgsRef, GenericParamDefKind, IsSuggestable, ParamEnv, Ty, + TyCtxt, TypeVisitableExt, }; use rustc_session::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS; use rustc_span::edit_distance::find_best_match_for_name; @@ -390,6 +389,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { infer_args, ); + if let Err(err) = &arg_count.correct + && let Some(reported) = err.reported + { + self.set_tainted_by_errors(reported); + } + // Skip processing if type has no generic parameters. // Traits always have `Self` as a generic parameter, which means they will not return early // here and so associated type bindings will be handled regardless of whether there are any @@ -568,6 +573,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { span, modifier: constness.as_str(), }); + self.set_tainted_by_errors(e); arg_count.correct = Err(GenericArgCountMismatch { reported: Some(e), invalid_args: vec![] }); } @@ -966,7 +972,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } } } - err.emit() + let reported = err.emit(); + self.set_tainted_by_errors(reported); + reported } // Search for a bound on a type parameter which includes the associated item @@ -1043,6 +1051,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { span, binding, ); + self.set_tainted_by_errors(reported); return Err(reported); }; debug!(?bound); @@ -1120,6 +1129,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { )); } let reported = err.emit(); + self.set_tainted_by_errors(reported); if !where_bounds.is_empty() { return Err(reported); } @@ -1374,6 +1384,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { assoc_ident.name, ) }; + self.set_tainted_by_errors(reported); return Err(reported); } }; @@ -1616,12 +1627,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let kind = tcx.def_kind_descr(kind, item); let msg = format!("{kind} `{name}` is private"); let def_span = tcx.def_span(item); - tcx.dcx() + let reported = tcx + .dcx() .struct_span_err(span, msg) .with_code(rustc_errors::error_code!(E0624)) .with_span_label(span, format!("private {kind}")) .with_span_label(def_span, format!("{kind} defined here")) .emit(); + self.set_tainted_by_errors(reported); } tcx.check_stability(item, Some(block), span, None); } @@ -1862,7 +1875,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { err.span_label(span, format!("not allowed on {what}")); } extend(&mut err); - err.emit(); + self.set_tainted_by_errors(err.emit()); emitted = true; } @@ -2184,7 +2197,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { { err.span_note(impl_.self_ty.span, "not a concrete type"); } - Ty::new_error(tcx, err.emit()) + let reported = err.emit(); + self.set_tainted_by_errors(reported); + Ty::new_error(tcx, reported) } else { ty } @@ -2306,6 +2321,114 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self.ast_ty_to_ty_inner(ast_ty, false, true) } + fn check_delegation_constraints(&self, sig_id: DefId, span: Span, emit: bool) -> bool { + let mut error_occured = false; + let sig_span = self.tcx().def_span(sig_id); + let mut try_emit = |descr| { + if emit { + self.tcx().dcx().emit_err(crate::errors::NotSupportedDelegation { + span, + descr, + callee_span: sig_span, + }); + } + error_occured = true; + }; + + if let Some(node) = self.tcx().hir().get_if_local(sig_id) + && let Some(decl) = node.fn_decl() + && let hir::FnRetTy::Return(ty) = decl.output + && let hir::TyKind::InferDelegation(_, _) = ty.kind + { + try_emit("recursive delegation"); + } + + let sig = self.tcx().fn_sig(sig_id).instantiate_identity(); + if sig.output().has_opaque_types() { + try_emit("delegation to a function with opaque type"); + } + + let sig_generics = self.tcx().generics_of(sig_id); + let parent = self.tcx().parent(self.item_def_id()); + let parent_generics = self.tcx().generics_of(parent); + + let parent_is_trait = (self.tcx().def_kind(parent) == DefKind::Trait) as usize; + let sig_has_self = sig_generics.has_self as usize; + + if sig_generics.count() > sig_has_self || parent_generics.count() > parent_is_trait { + try_emit("delegation with early bound generics"); + } + + if self.tcx().asyncness(sig_id) == ty::Asyncness::Yes { + try_emit("delegation to async functions"); + } + + if self.tcx().constness(sig_id) == hir::Constness::Const { + try_emit("delegation to const functions"); + } + + if sig.c_variadic() { + try_emit("delegation to variadic functions"); + // variadic functions are also `unsafe` and `extern "C"`. + // Do not emit same error multiple times. + return error_occured; + } + + if let hir::Unsafety::Unsafe = sig.unsafety() { + try_emit("delegation to unsafe functions"); + } + + if abi::Abi::Rust != sig.abi() { + try_emit("delegation to non Rust ABI functions"); + } + + error_occured + } + + fn ty_from_delegation( + &self, + sig_id: DefId, + idx: hir::InferDelegationKind, + span: Span, + ) -> Ty<'tcx> { + if self.check_delegation_constraints(sig_id, span, idx == hir::InferDelegationKind::Output) + { + let e = self.tcx().dcx().span_delayed_bug(span, "not supported delegation case"); + self.set_tainted_by_errors(e); + return Ty::new_error(self.tcx(), e); + }; + let sig = self.tcx().fn_sig(sig_id); + let sig_generics = self.tcx().generics_of(sig_id); + + let parent = self.tcx().parent(self.item_def_id()); + let parent_def_kind = self.tcx().def_kind(parent); + + let sig = if let DefKind::Impl { .. } = parent_def_kind + && sig_generics.has_self + { + // Generic params can't be here except the trait self type. + // They are not supported yet. + assert_eq!(sig_generics.count(), 1); + assert_eq!(self.tcx().generics_of(parent).count(), 0); + + let self_ty = self.tcx().type_of(parent).instantiate_identity(); + let generic_self_ty = ty::GenericArg::from(self_ty); + let substs = self.tcx().mk_args_from_iter(std::iter::once(generic_self_ty)); + sig.instantiate(self.tcx(), substs) + } else { + sig.instantiate_identity() + }; + + // Bound vars are also inherited from `sig_id`. They will be + // rebinded later in `ty_of_fn`. + let sig = sig.skip_binder(); + + match idx { + hir::InferDelegationKind::Input(id) => sig.inputs()[id], + hir::InferDelegationKind::Output => sig.output(), + } + } + /// Turns a `hir::Ty` into a `Ty`. For diagnostics' purposes we keep track of whether trait /// objects are borrowed like `&dyn Trait` to avoid emitting redundant errors. #[instrument(level = "debug", skip(self), ret)] @@ -2313,6 +2436,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let tcx = self.tcx(); let result_ty = match &ast_ty.kind { + hir::TyKind::InferDelegation(sig_id, idx) => { + self.ty_from_delegation(*sig_id, *idx, ast_ty.span) + } hir::TyKind::Slice(ty) => Ty::new_slice(tcx, self.ast_ty_to_ty(ty)), hir::TyKind::Ptr(mt) => { Ty::new_ptr(tcx, ty::TypeAndMut { ty: self.ast_ty_to_ty(mt.ty), mutbl: mt.mutbl }) @@ -2504,7 +2630,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { hir_ty: Option<&hir::Ty<'_>>, ) -> ty::PolyFnSig<'tcx> { let tcx = self.tcx(); - let bound_vars = tcx.late_bound_vars(hir_id); + let bound_vars = if let hir::FnRetTy::Return(ret_ty) = decl.output + && let hir::TyKind::InferDelegation(sig_id, _) = ret_ty.kind + { + tcx.fn_sig(sig_id).skip_binder().bound_vars() + } else { + tcx.late_bound_vars(hir_id) + }; debug!(?bound_vars); // We proactively collect all the inferred type params to emit a single error per fn def. @@ -2586,7 +2718,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ); } - diag.emit(); + self.set_tainted_by_errors(diag.emit()); } // Find any late-bound regions declared in return type that do @@ -2686,7 +2818,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { err.note("consider introducing a named lifetime parameter"); } - err.emit(); + self.set_tainted_by_errors(err.emit()); } } @@ -2725,7 +2857,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // error. let r = derived_region_bounds[0]; if derived_region_bounds[1..].iter().any(|r1| r != *r1) { - tcx.dcx().emit_err(AmbiguousLifetimeBound { span }); + self.set_tainted_by_errors(tcx.dcx().emit_err(AmbiguousLifetimeBound { span })); } Some(r) } diff --git a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs index ea2f5f50b5c60..f77f250cd288e 100644 --- a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs +++ b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs @@ -116,7 +116,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { for more information on them, visit \ ", ); - err.emit(); + self.set_tainted_by_errors(err.emit()); } if regular_traits.is_empty() && auto_traits.is_empty() { @@ -127,6 +127,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .map(|trait_ref| tcx.def_span(trait_ref)); let reported = tcx.dcx().emit_err(TraitObjectDeclaredWithNoTraits { span, trait_alias_span }); + self.set_tainted_by_errors(reported); return Ty::new_error(tcx, reported); } @@ -290,7 +291,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { if references_self { let def_id = i.bottom().0.def_id(); - struct_span_code_err!( + let reported = struct_span_code_err!( tcx.dcx(), i.bottom().1, E0038, @@ -303,6 +304,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .error_msg(), ) .emit(); + self.set_tainted_by_errors(reported); } ty::ExistentialTraitRef { def_id: trait_ref.def_id, args } @@ -389,6 +391,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } else { err.emit() }; + self.set_tainted_by_errors(e); ty::Region::new_error(tcx, e) }) } diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index c9f89a0c3ef32..e557f36037b6c 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -35,6 +35,7 @@ use rustc_target::spec::abi; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamName; use rustc_trait_selection::traits::ObligationCtxt; +use std::cell::Cell; use std::iter; use std::ops::Bound; @@ -119,6 +120,7 @@ pub fn provide(providers: &mut Providers) { pub struct ItemCtxt<'tcx> { tcx: TyCtxt<'tcx>, item_def_id: LocalDefId, + tainted_by_errors: Cell>, } /////////////////////////////////////////////////////////////////////////// @@ -343,7 +345,7 @@ fn bad_placeholder<'tcx>( impl<'tcx> ItemCtxt<'tcx> { pub fn new(tcx: TyCtxt<'tcx>, item_def_id: LocalDefId) -> ItemCtxt<'tcx> { - ItemCtxt { tcx, item_def_id } + ItemCtxt { tcx, item_def_id, tainted_by_errors: Cell::new(None) } } pub fn to_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> { @@ -357,6 +359,13 @@ impl<'tcx> ItemCtxt<'tcx> { pub fn node(&self) -> hir::Node<'tcx> { self.tcx.hir_node(self.hir_id()) } + + fn check_tainted_by_errors(&self) -> Result<(), ErrorGuaranteed> { + match self.tainted_by_errors.get() { + Some(err) => Err(err), + None => Ok(()), + } + } } impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> { @@ -492,8 +501,8 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> { ty.ty_adt_def() } - fn set_tainted_by_errors(&self, _: ErrorGuaranteed) { - // There's no obvious place to track this, so just let it go. + fn set_tainted_by_errors(&self, err: ErrorGuaranteed) { + self.tainted_by_errors.set(Some(err)); } fn record_ty(&self, _hir_id: hir::HirId, _ty: Ty<'tcx>, _span: Span) { diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 3ceea3dc7ae3f..b936b0c080542 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -513,7 +513,11 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder { + #[primary_span] + pub span: Span, + pub descr: &'a str, + #[label] + pub callee_span: Span, +} diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 1eaec9970537d..d36e0892d19d9 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -320,7 +320,7 @@ impl<'a> State<'a> { self.word("/*ERROR*/"); self.pclose(); } - hir::TyKind::Infer => { + hir::TyKind::Infer | hir::TyKind::InferDelegation(..) => { self.word("_"); } } diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index 7edb5912dd530..b6b332993151f 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -802,7 +802,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .explicit_item_bounds(def_id) .iter_instantiated_copied(self.tcx, args) .find_map(|(p, s)| get_future_output(p.as_predicate(), s))?, - ty::Error(_) => return None, + ty::Error(_) => return Some(ret_ty), _ => span_bug!( closure_span, "async fn coroutine return type not an inference variable: {ret_ty}" diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index c56a028321aef..3430a5fb00dc9 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -498,14 +498,14 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { // order when emitting them. let err = self.tcx().dcx().struct_span_err(span, format!("user args: {user_args:?}")); - err.buffer(&mut errors_buffer); + errors_buffer.push(err); } } if !errors_buffer.is_empty() { errors_buffer.sort_by_key(|diag| diag.span.primary_span()); - for diag in errors_buffer { - self.tcx().dcx().emit_diagnostic(diag); + for err in errors_buffer { + err.emit(); } } } diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 6c000380e713a..03335996c0354 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -82,7 +82,7 @@ pub(crate) fn parse_cfg(dcx: &DiagCtxt, cfgs: Vec) -> Cfg { Ok(..) => {} Err(err) => err.cancel(), }, - Err(errs) => drop(errs), + Err(errs) => errs.into_iter().for_each(|err| err.cancel()), } // If the user tried to use a key="value" flag, but is missing the quotes, provide @@ -129,9 +129,12 @@ pub(crate) fn parse_check_cfg(dcx: &DiagCtxt, specs: Vec) -> CheckCfg { error!("expected `cfg(name, values(\"value1\", \"value2\", ... \"valueN\"))`") }; - let Ok(mut parser) = maybe_new_parser_from_source_str(&sess, filename, s.to_string()) - else { - expected_error(); + let mut parser = match maybe_new_parser_from_source_str(&sess, filename, s.to_string()) { + Ok(parser) => parser, + Err(errs) => { + errs.into_iter().for_each(|err| err.cancel()); + expected_error(); + } }; let meta_item = match parser.parse_meta_item() { diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs index ec5edceb26997..18e198eb9fcab 100644 --- a/compiler/rustc_middle/src/mir/coverage.rs +++ b/compiler/rustc_middle/src/mir/coverage.rs @@ -158,18 +158,36 @@ pub struct Expression { pub rhs: CovTerm, } +#[derive(Clone, Debug)] +#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] +pub enum MappingKind { + /// Associates a normal region of code with a counter/expression/zero. + Code(CovTerm), +} + +impl MappingKind { + /// Iterator over all coverage terms in this mapping kind. + pub fn terms(&self) -> impl Iterator { + let one = |a| std::iter::once(a); + match *self { + Self::Code(term) => one(term), + } + } + + /// Returns a copy of this mapping kind, in which all coverage terms have + /// been replaced with ones returned by the given function. + pub fn map_terms(&self, map_fn: impl Fn(CovTerm) -> CovTerm) -> Self { + match *self { + Self::Code(term) => Self::Code(map_fn(term)), + } + } +} + #[derive(Clone, Debug)] #[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] pub struct Mapping { + pub kind: MappingKind, pub code_region: CodeRegion, - - /// Indicates whether this mapping uses a counter value, expression value, - /// or zero value. - /// - /// FIXME: When we add support for mapping kinds other than `Code` - /// (e.g. branch regions, expansion regions), replace this with a dedicated - /// mapping-kind enum. - pub term: CovTerm, } /// Stores per-function coverage information attached to a `mir::Body`, diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index a1e5d73a0fdb1..1a6b0f4031d38 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -493,8 +493,8 @@ fn write_function_coverage_info( for (id, expression) in expressions.iter_enumerated() { writeln!(w, "{INDENT}coverage {id:?} => {expression:?};")?; } - for coverage::Mapping { term, code_region } in mappings { - writeln!(w, "{INDENT}coverage {term:?} => {code_region:?};")?; + for coverage::Mapping { kind, code_region } in mappings { + writeln!(w, "{INDENT}coverage {kind:?} => {code_region:?};")?; } writeln!(w)?; diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 9e8d7c2ef3ecb..ad9296a4cc88a 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -42,7 +42,7 @@ use rustc_data_structures::unord::UnordMap; use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed, StashKey}; use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind, DocLinkResMap, LifetimeRes, Res}; -use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap}; +use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap, LocalDefIdSet}; use rustc_index::IndexVec; use rustc_macros::HashStable; use rustc_query_system::ich::StableHashingContext; @@ -202,6 +202,10 @@ pub struct ResolverAstLowering { /// Lints that were emitted by the resolver and early lints. pub lint_buffer: Steal, + + /// Information about functions signatures for delegation items expansion + pub has_self: LocalDefIdSet, + pub fn_parameter_counts: LocalDefIdMap, } #[derive(Clone, Copy, Debug)] diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index dcd7014f4fc90..a11d224e8f1b5 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -9,7 +9,7 @@ mod tests; use self::counters::{BcbCounter, CoverageCounters}; use self::graph::{BasicCoverageBlock, CoverageGraph}; -use self::spans::CoverageSpans; +use self::spans::{BcbMapping, BcbMappingKind, CoverageSpans}; use crate::MirPass; @@ -141,22 +141,21 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { let file_name = Symbol::intern(&source_file.name.for_codegen(self.tcx.sess).to_string_lossy()); + let term_for_bcb = |bcb| { + coverage_counters + .bcb_counter(bcb) + .expect("all BCBs with spans were given counters") + .as_term() + }; + coverage_spans - .bcbs_with_coverage_spans() - // For each BCB with spans, get a coverage term for its counter. - .map(|(bcb, spans)| { - let term = coverage_counters - .bcb_counter(bcb) - .expect("all BCBs with spans were given counters") - .as_term(); - (term, spans) - }) - // Flatten the spans into individual term/span pairs. - .flat_map(|(term, spans)| spans.iter().map(move |&span| (term, span))) - // Convert each span to a code region, and create the final mapping. - .filter_map(|(term, span)| { + .all_bcb_mappings() + .filter_map(|&BcbMapping { kind: bcb_mapping_kind, span }| { + let kind = match bcb_mapping_kind { + BcbMappingKind::Code(bcb) => MappingKind::Code(term_for_bcb(bcb)), + }; let code_region = make_code_region(source_map, file_name, span, body_span)?; - Some(Mapping { term, code_region }) + Some(Mapping { kind, code_region }) }) .collect::>() } diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs index 5983189984d91..81f6c8312061b 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans.rs @@ -1,5 +1,5 @@ use rustc_data_structures::graph::WithNumNodes; -use rustc_index::IndexVec; +use rustc_index::bit_set::BitSet; use rustc_middle::mir; use rustc_span::{BytePos, Span, DUMMY_SP}; @@ -8,9 +8,21 @@ use crate::coverage::ExtractedHirInfo; mod from_mir; +#[derive(Clone, Copy, Debug)] +pub(super) enum BcbMappingKind { + /// Associates an ordinary executable code span with its corresponding BCB. + Code(BasicCoverageBlock), +} + +#[derive(Debug)] +pub(super) struct BcbMapping { + pub(super) kind: BcbMappingKind, + pub(super) span: Span, +} + pub(super) struct CoverageSpans { - /// Map from BCBs to their list of coverage spans. - bcb_to_spans: IndexVec>, + bcb_has_mappings: BitSet, + mappings: Vec, } impl CoverageSpans { @@ -23,36 +35,42 @@ impl CoverageSpans { hir_info: &ExtractedHirInfo, basic_coverage_blocks: &CoverageGraph, ) -> Option { + let mut mappings = vec![]; + let coverage_spans = CoverageSpansGenerator::generate_coverage_spans( mir_body, hir_info, basic_coverage_blocks, ); + mappings.extend(coverage_spans.into_iter().map(|CoverageSpan { bcb, span, .. }| { + // Each span produced by the generator represents an ordinary code region. + BcbMapping { kind: BcbMappingKind::Code(bcb), span } + })); - if coverage_spans.is_empty() { + if mappings.is_empty() { return None; } - // Group the coverage spans by BCB, with the BCBs in sorted order. - let mut bcb_to_spans = IndexVec::from_elem_n(Vec::new(), basic_coverage_blocks.num_nodes()); - for CoverageSpan { bcb, span, .. } in coverage_spans { - bcb_to_spans[bcb].push(span); + // Identify which BCBs have one or more mappings. + let mut bcb_has_mappings = BitSet::new_empty(basic_coverage_blocks.num_nodes()); + let mut insert = |bcb| { + bcb_has_mappings.insert(bcb); + }; + for &BcbMapping { kind, span: _ } in &mappings { + match kind { + BcbMappingKind::Code(bcb) => insert(bcb), + } } - Some(Self { bcb_to_spans }) + Some(Self { bcb_has_mappings, mappings }) } pub(super) fn bcb_has_coverage_spans(&self, bcb: BasicCoverageBlock) -> bool { - !self.bcb_to_spans[bcb].is_empty() + self.bcb_has_mappings.contains(bcb) } - pub(super) fn bcbs_with_coverage_spans( - &self, - ) -> impl Iterator { - self.bcb_to_spans.iter_enumerated().filter_map(|(bcb, spans)| { - // Only yield BCBs that have at least one coverage span. - (!spans.is_empty()).then_some((bcb, spans.as_slice())) - }) + pub(super) fn all_bcb_mappings(&self) -> impl Iterator { + self.mappings.iter() } } diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 7db9291921f0e..d7ecf577ed676 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -7,7 +7,7 @@ use rustc_ast::ast::{self, AttrStyle}; use rustc_ast::token::{self, CommentKind, Delimiter, Token, TokenKind}; use rustc_ast::tokenstream::TokenStream; use rustc_ast::util::unicode::contains_text_flow_control_chars; -use rustc_errors::{error_code, Applicability, DiagCtxt, Diagnostic, StashKey}; +use rustc_errors::{error_code, Applicability, DiagCtxt, DiagnosticBuilder, StashKey}; use rustc_lexer::unescape::{self, EscapeError, Mode}; use rustc_lexer::{Base, DocStyle, RawStrError}; use rustc_lexer::{Cursor, LiteralKind}; @@ -42,12 +42,12 @@ pub struct UnmatchedDelim { pub candidate_span: Option, } -pub(crate) fn parse_token_trees<'a>( - sess: &'a ParseSess, - mut src: &'a str, +pub(crate) fn parse_token_trees<'sess, 'src>( + sess: &'sess ParseSess, + mut src: &'src str, mut start_pos: BytePos, override_span: Option, -) -> Result> { +) -> Result>> { // Skip `#!`, if present. if let Some(shebang_len) = rustc_lexer::strip_shebang(src) { src = &src[shebang_len..]; @@ -76,13 +76,13 @@ pub(crate) fn parse_token_trees<'a>( let mut buffer = Vec::with_capacity(1); for unmatched in unmatched_delims { if let Some(err) = make_unclosed_delims_error(unmatched, sess) { - err.buffer(&mut buffer); + buffer.push(err); } } if let Err(errs) = res { // Add unclosing delimiter or diff marker errors for err in errs { - err.buffer(&mut buffer); + buffer.push(err); } } Err(buffer) @@ -90,16 +90,16 @@ pub(crate) fn parse_token_trees<'a>( } } -struct StringReader<'a> { - sess: &'a ParseSess, +struct StringReader<'sess, 'src> { + sess: &'sess ParseSess, /// Initial position, read-only. start_pos: BytePos, /// The absolute offset within the source_map of the current character. pos: BytePos, /// Source text to tokenize. - src: &'a str, + src: &'src str, /// Cursor for getting lexer tokens. - cursor: Cursor<'a>, + cursor: Cursor<'src>, override_span: Option, /// When a "unknown start of token: \u{a0}" has already been emitted earlier /// in this file, it's safe to treat further occurrences of the non-breaking @@ -107,8 +107,8 @@ struct StringReader<'a> { nbsp_is_whitespace: bool, } -impl<'a> StringReader<'a> { - pub fn dcx(&self) -> &'a DiagCtxt { +impl<'sess, 'src> StringReader<'sess, 'src> { + pub fn dcx(&self) -> &'sess DiagCtxt { &self.sess.dcx } @@ -526,7 +526,7 @@ impl<'a> StringReader<'a> { /// Slice of the source text from `start` up to but excluding `self.pos`, /// meaning the slice does not include the character `self.ch`. - fn str_from(&self, start: BytePos) -> &'a str { + fn str_from(&self, start: BytePos) -> &'src str { self.str_from_to(start, self.pos) } @@ -537,12 +537,12 @@ impl<'a> StringReader<'a> { } /// Slice of the source text spanning from `start` up to but excluding `end`. - fn str_from_to(&self, start: BytePos, end: BytePos) -> &'a str { + fn str_from_to(&self, start: BytePos, end: BytePos) -> &'src str { &self.src[self.src_index(start)..self.src_index(end)] } /// Slice of the source text spanning from `start` until the end - fn str_from_to_end(&self, start: BytePos) -> &'a str { + fn str_from_to_end(&self, start: BytePos) -> &'src str { &self.src[self.src_index(start)..] } diff --git a/compiler/rustc_parse/src/lexer/tokentrees.rs b/compiler/rustc_parse/src/lexer/tokentrees.rs index 64b3928689afe..c9ff2d58e2c56 100644 --- a/compiler/rustc_parse/src/lexer/tokentrees.rs +++ b/compiler/rustc_parse/src/lexer/tokentrees.rs @@ -8,18 +8,18 @@ use rustc_ast_pretty::pprust::token_to_string; use rustc_errors::{Applicability, PErr}; use rustc_span::symbol::kw; -pub(super) struct TokenTreesReader<'a> { - string_reader: StringReader<'a>, +pub(super) struct TokenTreesReader<'sess, 'src> { + string_reader: StringReader<'sess, 'src>, /// The "next" token, which has been obtained from the `StringReader` but /// not yet handled by the `TokenTreesReader`. token: Token, diag_info: TokenTreeDiagInfo, } -impl<'a> TokenTreesReader<'a> { +impl<'sess, 'src> TokenTreesReader<'sess, 'src> { pub(super) fn parse_all_token_trees( - string_reader: StringReader<'a>, - ) -> (TokenStream, Result<(), Vec>>, Vec) { + string_reader: StringReader<'sess, 'src>, + ) -> (TokenStream, Result<(), Vec>>, Vec) { let mut tt_reader = TokenTreesReader { string_reader, token: Token::dummy(), @@ -35,7 +35,7 @@ impl<'a> TokenTreesReader<'a> { fn parse_token_trees( &mut self, is_delimited: bool, - ) -> (Spacing, TokenStream, Result<(), Vec>>) { + ) -> (Spacing, TokenStream, Result<(), Vec>>) { // Move past the opening delimiter. let (_, open_spacing) = self.bump(false); @@ -71,7 +71,7 @@ impl<'a> TokenTreesReader<'a> { } } - fn eof_err(&mut self) -> PErr<'a> { + fn eof_err(&mut self) -> PErr<'sess> { let msg = "this file contains an unclosed delimiter"; let mut err = self.string_reader.sess.dcx.struct_span_err(self.token.span, msg); for &(_, sp) in &self.diag_info.open_braces { @@ -99,7 +99,7 @@ impl<'a> TokenTreesReader<'a> { fn parse_token_tree_open_delim( &mut self, open_delim: Delimiter, - ) -> Result>> { + ) -> Result>> { // The span for beginning of the delimited section let pre_span = self.token.span; @@ -229,7 +229,11 @@ impl<'a> TokenTreesReader<'a> { (this_tok, this_spacing) } - fn unclosed_delim_err(&mut self, tts: TokenStream, mut errs: Vec>) -> Vec> { + fn unclosed_delim_err( + &mut self, + tts: TokenStream, + mut errs: Vec>, + ) -> Vec> { // If there are unclosed delims, see if there are diff markers and if so, point them // out instead of complaining about the unclosed delims. let mut parser = crate::stream_to_parser(self.string_reader.sess, tts, None); @@ -285,7 +289,7 @@ impl<'a> TokenTreesReader<'a> { return errs; } - fn close_delim_err(&mut self, delim: Delimiter) -> PErr<'a> { + fn close_delim_err(&mut self, delim: Delimiter) -> PErr<'sess> { // An unexpected closing delimiter (i.e., there is no // matching opening delimiter). let token_str = token_to_string(&self.token); diff --git a/compiler/rustc_parse/src/lexer/unicode_chars.rs b/compiler/rustc_parse/src/lexer/unicode_chars.rs index dac7569e385e7..a136abaa28bb8 100644 --- a/compiler/rustc_parse/src/lexer/unicode_chars.rs +++ b/compiler/rustc_parse/src/lexer/unicode_chars.rs @@ -337,7 +337,7 @@ const ASCII_ARRAY: &[(&str, &str, Option)] = &[ ]; pub(super) fn check_for_substitution( - reader: &StringReader<'_>, + reader: &StringReader<'_, '_>, pos: BytePos, ch: char, count: usize, diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index b93f08a21e311..c00e318f22709 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -19,7 +19,7 @@ use rustc_ast::tokenstream::TokenStream; use rustc_ast::{AttrItem, Attribute, MetaItem}; use rustc_ast_pretty::pprust; use rustc_data_structures::sync::Lrc; -use rustc_errors::{Diagnostic, FatalError, Level, PResult}; +use rustc_errors::{DiagnosticBuilder, FatalError, PResult}; use rustc_session::parse::ParseSess; use rustc_span::{FileName, SourceFile, Span}; @@ -45,14 +45,13 @@ rustc_fluent_macro::fluent_messages! { "../messages.ftl" } /// A variant of 'panictry!' that works on a `Vec` instead of a single /// `DiagnosticBuilder`. macro_rules! panictry_buffer { - ($handler:expr, $e:expr) => {{ - use rustc_errors::FatalError; + ($e:expr) => {{ use std::result::Result::{Err, Ok}; match $e { Ok(e) => e, Err(errs) => { for e in errs { - $handler.emit_diagnostic(e); + e.emit(); } FatalError.raise() } @@ -100,36 +99,41 @@ pub fn parse_stream_from_source_str( /// Creates a new parser from a source string. pub fn new_parser_from_source_str(sess: &ParseSess, name: FileName, source: String) -> Parser<'_> { - panictry_buffer!(&sess.dcx, maybe_new_parser_from_source_str(sess, name, source)) + panictry_buffer!(maybe_new_parser_from_source_str(sess, name, source)) } /// Creates a new parser from a source string. Returns any buffered errors from lexing the initial -/// token stream. +/// token stream; these must be consumed via `emit`, `cancel`, etc., otherwise a panic will occur +/// when they are dropped. pub fn maybe_new_parser_from_source_str( sess: &ParseSess, name: FileName, source: String, -) -> Result, Vec> { +) -> Result, Vec>> { maybe_source_file_to_parser(sess, sess.source_map().new_source_file(name, source)) } -/// Creates a new parser, handling errors as appropriate if the file doesn't exist. -/// If a span is given, that is used on an error as the source of the problem. +/// Creates a new parser, aborting if the file doesn't exist. If a span is given, that is used on +/// an error as the source of the problem. pub fn new_parser_from_file<'a>(sess: &'a ParseSess, path: &Path, sp: Option) -> Parser<'a> { - source_file_to_parser(sess, file_to_source_file(sess, path, sp)) -} + let source_file = sess.source_map().load_file(path).unwrap_or_else(|e| { + let msg = format!("couldn't read {}: {}", path.display(), e); + let mut err = sess.dcx.struct_fatal(msg); + if let Some(sp) = sp { + err.span(sp); + } + err.emit(); + }); -/// Given a session and a `source_file`, returns a parser. -fn source_file_to_parser(sess: &ParseSess, source_file: Lrc) -> Parser<'_> { - panictry_buffer!(&sess.dcx, maybe_source_file_to_parser(sess, source_file)) + panictry_buffer!(maybe_source_file_to_parser(sess, source_file)) } -/// Given a session and a `source_file`, return a parser. Returns any buffered errors from lexing the -/// initial token stream. +/// Given a session and a `source_file`, return a parser. Returns any buffered errors from lexing +/// the initial token stream. fn maybe_source_file_to_parser( sess: &ParseSess, source_file: Lrc, -) -> Result, Vec> { +) -> Result, Vec>> { let end_pos = source_file.end_position(); let stream = maybe_file_to_stream(sess, source_file, None)?; let mut parser = stream_to_parser(sess, stream, None); @@ -142,52 +146,22 @@ fn maybe_source_file_to_parser( // Base abstractions -/// Given a session and a path and an optional span (for error reporting), -/// add the path to the session's source_map and return the new source_file or -/// error when a file can't be read. -fn try_file_to_source_file( - sess: &ParseSess, - path: &Path, - spanopt: Option, -) -> Result, Diagnostic> { - sess.source_map().load_file(path).map_err(|e| { - let msg = format!("couldn't read {}: {}", path.display(), e); - let mut diag = Diagnostic::new(Level::Fatal, msg); - if let Some(sp) = spanopt { - diag.span(sp); - } - diag - }) -} - -/// Given a session and a path and an optional span (for error reporting), -/// adds the path to the session's `source_map` and returns the new `source_file`. -fn file_to_source_file(sess: &ParseSess, path: &Path, spanopt: Option) -> Lrc { - match try_file_to_source_file(sess, path, spanopt) { - Ok(source_file) => source_file, - Err(d) => { - sess.dcx.emit_diagnostic(d); - FatalError.raise(); - } - } -} - /// Given a `source_file`, produces a sequence of token trees. pub fn source_file_to_stream( sess: &ParseSess, source_file: Lrc, override_span: Option, ) -> TokenStream { - panictry_buffer!(&sess.dcx, maybe_file_to_stream(sess, source_file, override_span)) + panictry_buffer!(maybe_file_to_stream(sess, source_file, override_span)) } /// Given a source file, produces a sequence of token trees. Returns any buffered errors from /// parsing the token stream. -pub fn maybe_file_to_stream( - sess: &ParseSess, +fn maybe_file_to_stream<'sess>( + sess: &'sess ParseSess, source_file: Lrc, override_span: Option, -) -> Result> { +) -> Result>> { let src = source_file.src.as_ref().unwrap_or_else(|| { sess.dcx.bug(format!( "cannot lex `source_file` without source: {}", diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index bcff820da7960..3bd8ae0258628 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -252,6 +252,8 @@ impl<'a> Parser<'a> { { // IMPL ITEM self.parse_item_impl(attrs, def_())? + } else if self.is_reuse_path_item() { + self.parse_item_delegation()? } else if self.check_keyword(kw::Mod) || self.check_keyword(kw::Unsafe) && self.is_keyword_ahead(1, &[kw::Mod]) { @@ -349,11 +351,18 @@ impl<'a> Parser<'a> { /// When parsing a statement, would the start of a path be an item? pub(super) fn is_path_start_item(&mut self) -> bool { self.is_kw_followed_by_ident(kw::Union) // no: `union::b`, yes: `union U { .. }` + || self.is_reuse_path_item() || self.check_auto_or_unsafe_trait_item() // no: `auto::b`, yes: `auto trait X { .. }` || self.is_async_fn() // no(2015): `async::b`, yes: `async fn` || matches!(self.is_macro_rules_item(), IsMacroRulesItem::Yes{..}) // no: `macro_rules::b`, yes: `macro_rules! mac` } + fn is_reuse_path_item(&mut self) -> bool { + // no: `reuse ::path` for compatibility reasons with macro invocations + self.token.is_keyword(kw::Reuse) + && self.look_ahead(1, |t| t.is_path_start() && t.kind != token::ModSep) + } + /// Are we sure this could not possibly be a macro invocation? fn isnt_macro_invocation(&mut self) -> bool { self.check_ident() && self.look_ahead(1, |t| *t != token::Not && *t != token::ModSep) @@ -655,6 +664,33 @@ impl<'a> Parser<'a> { Ok((Ident::empty(), item_kind)) } + fn parse_item_delegation(&mut self) -> PResult<'a, ItemInfo> { + let span = self.token.span; + self.expect_keyword(kw::Reuse)?; + + let (qself, path) = if self.eat_lt() { + let (qself, path) = self.parse_qpath(PathStyle::Expr)?; + (Some(qself), path) + } else { + (None, self.parse_path(PathStyle::Expr)?) + }; + + let body = if self.check(&token::OpenDelim(Delimiter::Brace)) { + Some(self.parse_block()?) + } else { + self.expect(&token::Semi)?; + None + }; + let span = span.to(self.prev_token.span); + self.sess.gated_spans.gate(sym::fn_delegation, span); + + let ident = path.segments.last().map(|seg| seg.ident).unwrap_or(Ident::empty()); + Ok(( + ident, + ItemKind::Delegation(Box::new(Delegation { id: DUMMY_NODE_ID, qself, path, body })), + )) + } + fn parse_item_list( &mut self, attrs: &mut AttrVec, diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs index c2392620cb285..ff29fc5929c76 100644 --- a/compiler/rustc_passes/src/hir_stats.rs +++ b/compiler/rustc_passes/src/hir_stats.rs @@ -341,6 +341,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { record_variants!( (self, t, t.kind, Id::Node(t.hir_id), hir, Ty, TyKind), [ + InferDelegation, Slice, Array, Ptr, @@ -521,7 +522,8 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { TraitAlias, Impl, MacCall, - MacroDef + MacroDef, + Delegation ] ); ast_visit::walk_item(self, i) @@ -645,7 +647,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { fn visit_assoc_item(&mut self, i: &'v ast::AssocItem, ctxt: ast_visit::AssocCtxt) { record_variants!( (self, i, i.kind, Id::None, ast, AssocItem, AssocItemKind), - [Const, Fn, Type, MacCall] + [Const, Fn, Type, MacCall, Delegation] ); ast_visit::walk_assoc_item(self, i, ctxt); } diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs index 647f4d0e08419..6aeaa8945fb59 100644 --- a/compiler/rustc_passes/src/lang_items.rs +++ b/compiler/rustc_passes/src/lang_items.rs @@ -271,7 +271,7 @@ impl<'ast, 'tcx> visit::Visitor<'ast> for LanguageItemCollector<'ast, 'tcx> { ast::ItemKind::Use(_) => Target::Use, ast::ItemKind::Static(_) => Target::Static, ast::ItemKind::Const(_) => Target::Const, - ast::ItemKind::Fn(_) => Target::Fn, + ast::ItemKind::Fn(_) | ast::ItemKind::Delegation(..) => Target::Fn, ast::ItemKind::Mod(_, _) => Target::Mod, ast::ItemKind::ForeignMod(_) => Target::ForeignFn, ast::ItemKind::GlobalAsm(_) => Target::GlobalAsm, @@ -315,24 +315,29 @@ impl<'ast, 'tcx> visit::Visitor<'ast> for LanguageItemCollector<'ast, 'tcx> { fn visit_assoc_item(&mut self, i: &'ast ast::AssocItem, ctxt: visit::AssocCtxt) { let (target, generics) = match &i.kind { - ast::AssocItemKind::Fn(fun) => ( - match &self.parent_item.unwrap().kind { - ast::ItemKind::Impl(i) => { - if i.of_trait.is_some() { - Target::Method(MethodKind::Trait { body: fun.body.is_some() }) - } else { - Target::Method(MethodKind::Inherent) + ast::AssocItemKind::Fn(..) | ast::AssocItemKind::Delegation(..) => { + let (body, generics) = if let ast::AssocItemKind::Fn(fun) = &i.kind { + (fun.body.is_some(), Some(&fun.generics)) + } else { + (true, None) + }; + ( + match &self.parent_item.unwrap().kind { + ast::ItemKind::Impl(i) => { + if i.of_trait.is_some() { + Target::Method(MethodKind::Trait { body }) + } else { + Target::Method(MethodKind::Inherent) + } } - } - ast::ItemKind::Trait(_) => { - Target::Method(MethodKind::Trait { body: fun.body.is_some() }) - } - _ => unreachable!(), - }, - &fun.generics, - ), - ast::AssocItemKind::Const(ct) => (Target::AssocConst, &ct.generics), - ast::AssocItemKind::Type(ty) => (Target::AssocTy, &ty.generics), + ast::ItemKind::Trait(_) => Target::Method(MethodKind::Trait { body }), + _ => unreachable!(), + }, + generics, + ) + } + ast::AssocItemKind::Const(ct) => (Target::AssocConst, Some(&ct.generics)), + ast::AssocItemKind::Type(ty) => (Target::AssocTy, Some(&ty.generics)), ast::AssocItemKind::MacCall(_) => unreachable!("macros should have been expanded"), }; @@ -341,7 +346,7 @@ impl<'ast, 'tcx> visit::Visitor<'ast> for LanguageItemCollector<'ast, 'tcx> { self.resolver.node_id_to_def_id[&i.id], &i.attrs, i.span, - Some(generics), + generics, ); visit::walk_assoc_item(self, i, ctxt); diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 9ccfde5e3c621..a4e2f9e3ff8cd 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -16,7 +16,7 @@ use crate::{Resolver, ResolverArenas, Segment, ToNameBinding, VisResolutionError use rustc_ast::visit::{self, AssocCtxt, Visitor}; use rustc_ast::{self as ast, AssocItem, AssocItemKind, MetaItemKind, StmtKind}; -use rustc_ast::{Block, Fn, ForeignItem, ForeignItemKind, Impl, Item, ItemKind, NodeId}; +use rustc_ast::{Block, ForeignItem, ForeignItemKind, Impl, Item, ItemKind, NodeId}; use rustc_attr as attr; use rustc_data_structures::sync::Lrc; use rustc_errors::{struct_span_code_err, Applicability}; @@ -686,10 +686,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { } // These items live in the value namespace. - ItemKind::Static(..) => { - self.r.define(parent, ident, ValueNS, (res, vis, sp, expansion)); - } - ItemKind::Const(..) => { + ItemKind::Const(..) | ItemKind::Delegation(..) | ItemKind::Static(..) => { self.r.define(parent, ident, ValueNS, (res, vis, sp, expansion)); } ItemKind::Fn(..) => { @@ -701,11 +698,11 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { } // These items live in the type namespace. - ItemKind::TyAlias(..) => { + ItemKind::TyAlias(..) | ItemKind::TraitAlias(..) => { self.r.define(parent, ident, TypeNS, (res, vis, sp, expansion)); } - ItemKind::Enum(_, _) => { + ItemKind::Enum(_, _) | ItemKind::Trait(..) => { let module = self.r.new_module( Some(parent), ModuleKind::Def(def_kind, def_id, ident.name), @@ -717,10 +714,6 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { self.parent_scope.module = module; } - ItemKind::TraitAlias(..) => { - self.r.define(parent, ident, TypeNS, (res, vis, sp, expansion)); - } - // These items live in both the type and value namespaces. ItemKind::Struct(ref vdata, _) => { // Define a name in the type namespace. @@ -778,19 +771,6 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { self.insert_field_visibilities_local(def_id, vdata); } - ItemKind::Trait(..) => { - // Add all the items within to a new module. - let module = self.r.new_module( - Some(parent), - ModuleKind::Def(def_kind, def_id, ident.name), - expansion.to_expn_id(), - item.span, - parent.no_implicit_prelude, - ); - self.r.define(parent, ident, TypeNS, (module, vis, sp, expansion)); - self.parent_scope.module = module; - } - // These items do not add names to modules. ItemKind::Impl(box Impl { of_trait: Some(..), .. }) => { self.r.trait_impl_items.insert(local_def_id); @@ -1358,13 +1338,9 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { if ctxt == AssocCtxt::Trait { let ns = match item.kind { - AssocItemKind::Const(..) => ValueNS, - AssocItemKind::Fn(box Fn { ref sig, .. }) => { - if sig.decl.has_self() { - self.r.has_self.insert(local_def_id); - } - ValueNS - } + AssocItemKind::Const(..) + | AssocItemKind::Delegation(..) + | AssocItemKind::Fn(..) => ValueNS, AssocItemKind::Type(..) => TypeNS, AssocItemKind::MacCall(_) => bug!(), // handled above }; diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index 02553d5007155..b77102c085c59 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -111,7 +111,7 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { ItemKind::TyAlias(..) => DefKind::TyAlias, ItemKind::Static(s) => DefKind::Static(s.mutability), ItemKind::Const(..) => DefKind::Const, - ItemKind::Fn(..) => DefKind::Fn, + ItemKind::Fn(..) | ItemKind::Delegation(..) => DefKind::Fn, ItemKind::MacroDef(..) => { let macro_data = self.resolver.compile_macro(i, self.resolver.tcx.sess.edition()); let macro_kind = macro_data.ext.macro_kind(); @@ -259,7 +259,7 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { fn visit_assoc_item(&mut self, i: &'a AssocItem, ctxt: visit::AssocCtxt) { let def_kind = match &i.kind { - AssocItemKind::Fn(..) => DefKind::AssocFn, + AssocItemKind::Fn(..) | AssocItemKind::Delegation(..) => DefKind::AssocFn, AssocItemKind::Const(..) => DefKind::AssocConst, AssocItemKind::Type(..) => DefKind::AssocTy, AssocItemKind::MacCall(..) => return self.visit_macro_invoc(i.id), diff --git a/compiler/rustc_resolve/src/effective_visibilities.rs b/compiler/rustc_resolve/src/effective_visibilities.rs index 50352169221d7..3443bbe6e1158 100644 --- a/compiler/rustc_resolve/src/effective_visibilities.rs +++ b/compiler/rustc_resolve/src/effective_visibilities.rs @@ -277,7 +277,8 @@ impl<'r, 'ast, 'tcx> Visitor<'ast> for EffectiveVisibilitiesVisitor<'ast, 'r, 't | ast::ItemKind::TraitAlias(..) | ast::ItemKind::MacroDef(..) | ast::ItemKind::ForeignMod(..) - | ast::ItemKind::Fn(..) => return, + | ast::ItemKind::Fn(..) + | ast::ItemKind::Delegation(..) => return, } } } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 4a3c8dfe3d729..b9e603a499266 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -394,13 +394,18 @@ pub(crate) enum PathSource<'a> { TupleStruct(Span, &'a [Span]), // `m::A::B` in `::B::C`. TraitItem(Namespace), + // Paths in delegation item + Delegation, } impl<'a> PathSource<'a> { fn namespace(self) -> Namespace { match self { PathSource::Type | PathSource::Trait(_) | PathSource::Struct => TypeNS, - PathSource::Expr(..) | PathSource::Pat | PathSource::TupleStruct(..) => ValueNS, + PathSource::Expr(..) + | PathSource::Pat + | PathSource::TupleStruct(..) + | PathSource::Delegation => ValueNS, PathSource::TraitItem(ns) => ns, } } @@ -412,7 +417,7 @@ impl<'a> PathSource<'a> { | PathSource::Pat | PathSource::Struct | PathSource::TupleStruct(..) => true, - PathSource::Trait(_) | PathSource::TraitItem(..) => false, + PathSource::Trait(_) | PathSource::TraitItem(..) | PathSource::Delegation => false, } } @@ -454,6 +459,7 @@ impl<'a> PathSource<'a> { }, _ => "value", }, + PathSource::Delegation => "function", } } @@ -521,6 +527,7 @@ impl<'a> PathSource<'a> { Res::Def(DefKind::AssocTy, _) if ns == TypeNS => true, _ => false, }, + PathSource::Delegation => matches!(res, Res::Def(DefKind::Fn | DefKind::AssocFn, _)), } } @@ -533,8 +540,8 @@ impl<'a> PathSource<'a> { (PathSource::Type, false) => error_code!(E0412), (PathSource::Struct, true) => error_code!(E0574), (PathSource::Struct, false) => error_code!(E0422), - (PathSource::Expr(..), true) => error_code!(E0423), - (PathSource::Expr(..), false) => error_code!(E0425), + (PathSource::Expr(..), true) | (PathSource::Delegation, true) => error_code!(E0423), + (PathSource::Expr(..), false) | (PathSource::Delegation, false) => error_code!(E0425), (PathSource::Pat | PathSource::TupleStruct(..), true) => error_code!(E0532), (PathSource::Pat | PathSource::TupleStruct(..), false) => error_code!(E0531), (PathSource::TraitItem(..), true) => error_code!(E0575), @@ -1805,7 +1812,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { PathSource::Expr(..) | PathSource::Pat | PathSource::Struct - | PathSource::TupleStruct(..) => true, + | PathSource::TupleStruct(..) + | PathSource::Delegation => true, }; if inferred { // Do not create a parameter for patterns and expressions: type checking can infer @@ -2514,6 +2522,10 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { visit::walk_item(self, item); } + ItemKind::Delegation(ref delegation) => { + self.resolve_delegation(delegation); + } + ItemKind::ExternCrate(..) => {} ItemKind::MacCall(_) => panic!("unexpanded macro in resolve!"), @@ -2790,6 +2802,9 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { AssocItemKind::Fn(box Fn { generics, .. }) => { walk_assoc_item(self, generics, LifetimeBinderKind::Function, item); } + AssocItemKind::Delegation(delegation) => { + self.resolve_delegation(delegation); + } AssocItemKind::Type(box TyAlias { generics, .. }) => self .with_lifetime_rib(LifetimeRibKind::AnonymousReportError, |this| { walk_assoc_item(this, generics, LifetimeBinderKind::Item, item) @@ -3036,6 +3051,19 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { }, ); } + AssocItemKind::Delegation(box delegation) => { + debug!("resolve_implementation AssocItemKind::Delegation"); + self.check_trait_item( + item.id, + item.ident, + &item.kind, + ValueNS, + item.span, + seen_trait_items, + |i, s, c| MethodNotMemberOfTrait(i, s, c), + ); + self.resolve_delegation(delegation); + } AssocItemKind::MacCall(_) => { panic!("unexpanded macro in resolve!") } @@ -3123,7 +3151,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { match (def_kind, kind) { (DefKind::AssocTy, AssocItemKind::Type(..)) | (DefKind::AssocFn, AssocItemKind::Fn(..)) - | (DefKind::AssocConst, AssocItemKind::Const(..)) => { + | (DefKind::AssocConst, AssocItemKind::Const(..)) + | (DefKind::AssocFn, AssocItemKind::Delegation(..)) => { self.r.record_partial_res(id, PartialRes::new(res)); return; } @@ -3136,6 +3165,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { AssocItemKind::Const(..) => (rustc_errors::error_code!(E0323), "const"), AssocItemKind::Fn(..) => (rustc_errors::error_code!(E0324), "method"), AssocItemKind::Type(..) => (rustc_errors::error_code!(E0325), "type"), + AssocItemKind::Delegation(..) => (rustc_errors::error_code!(E0324), "method"), AssocItemKind::MacCall(..) => span_bug!(span, "unexpanded macro"), }; let trait_path = path_names_to_string(path); @@ -3159,6 +3189,32 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { }) } + fn resolve_delegation(&mut self, delegation: &'ast Delegation) { + self.smart_resolve_path( + delegation.id, + &delegation.qself, + &delegation.path, + PathSource::Delegation, + ); + if let Some(qself) = &delegation.qself { + self.visit_ty(&qself.ty); + } + self.visit_path(&delegation.path, delegation.id); + if let Some(body) = &delegation.body { + // `PatBoundCtx` is not necessary in this context + let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())]; + + let span = delegation.path.segments.last().unwrap().ident.span; + self.fresh_binding( + Ident::new(kw::SelfLower, span), + delegation.id, + PatternSource::FnParam, + &mut bindings, + ); + self.visit_block(body); + } + } + fn resolve_params(&mut self, params: &'ast [Param]) { let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())]; self.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| { @@ -4551,13 +4607,24 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { } } -struct LifetimeCountVisitor<'a, 'b, 'tcx> { +/// Walks the whole crate in DFS order, visiting each item, counting the declared number of +/// lifetime generic parameters and function parameters. +struct ItemInfoCollector<'a, 'b, 'tcx> { r: &'b mut Resolver<'a, 'tcx>, } -/// Walks the whole crate in DFS order, visiting each item, counting the declared number of -/// lifetime generic parameters. -impl<'ast> Visitor<'ast> for LifetimeCountVisitor<'_, '_, '_> { +impl ItemInfoCollector<'_, '_, '_> { + fn collect_fn_info(&mut self, sig: &FnSig, id: NodeId) { + let def_id = self.r.local_def_id(id); + self.r.fn_parameter_counts.insert(def_id, sig.decl.inputs.len()); + + if sig.decl.has_self() { + self.r.has_self.insert(def_id); + } + } +} + +impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> { fn visit_item(&mut self, item: &'ast Item) { match &item.kind { ItemKind::TyAlias(box TyAlias { ref generics, .. }) @@ -4569,6 +4636,10 @@ impl<'ast> Visitor<'ast> for LifetimeCountVisitor<'_, '_, '_> { | ItemKind::Impl(box Impl { ref generics, .. }) | ItemKind::Trait(box Trait { ref generics, .. }) | ItemKind::TraitAlias(ref generics, _) => { + if let ItemKind::Fn(box Fn { ref sig, .. }) = &item.kind { + self.collect_fn_info(sig, item.id); + } + let def_id = self.r.local_def_id(item.id); let count = generics .params @@ -4586,14 +4657,27 @@ impl<'ast> Visitor<'ast> for LifetimeCountVisitor<'_, '_, '_> { | ItemKind::MacroDef(..) | ItemKind::GlobalAsm(..) | ItemKind::MacCall(..) => {} + ItemKind::Delegation(..) => { + // Delegated functions have lifetimes, their count is not necessarily zero. + // But skipping the delegation items here doesn't mean that the count will be considered zero, + // it means there will be a panic when retrieving the count, + // but for delegation items we are never actually retrieving that count in practice. + } } visit::walk_item(self, item) } + + fn visit_assoc_item(&mut self, item: &'ast AssocItem, ctxt: AssocCtxt) { + if let AssocItemKind::Fn(box Fn { ref sig, .. }) = &item.kind { + self.collect_fn_info(sig, item.id); + } + visit::walk_assoc_item(self, item, ctxt); + } } impl<'a, 'tcx> Resolver<'a, 'tcx> { pub(crate) fn late_resolve_crate(&mut self, krate: &Crate) { - visit::walk_crate(&mut LifetimeCountVisitor { r: self }, krate); + visit::walk_crate(&mut ItemInfoCollector { r: self }, krate); let mut late_resolution_visitor = LateResolutionVisitor::new(self); late_resolution_visitor.resolve_doc_links(&krate.attrs, MaybeExported::Ok(CRATE_NODE_ID)); visit::walk_crate(&mut late_resolution_visitor, krate); diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 2f476ae6cbcc1..58ff4d8c79349 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -656,7 +656,10 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { let typo_sugg = self .lookup_typo_candidate(path, following_seg, source.namespace(), is_expected) .to_opt_suggestion(); - if path.len() == 1 && self.self_type_is_available() { + if path.len() == 1 + && !matches!(source, PathSource::Delegation) + && self.self_type_is_available() + { if let Some(candidate) = self.lookup_assoc_candidate(ident, ns, is_expected, source.is_call()) { @@ -1899,6 +1902,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { (AssocItemKind::Const(..), Res::Def(DefKind::AssocConst, _)) => true, (AssocItemKind::Fn(_), Res::Def(DefKind::AssocFn, _)) => true, (AssocItemKind::Type(..), Res::Def(DefKind::AssocTy, _)) => true, + (AssocItemKind::Delegation(_), Res::Def(DefKind::AssocFn, _)) => true, _ => false, }) .map(|(key, _)| key.ident.name) @@ -1960,6 +1964,12 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { } ast::AssocItemKind::Fn(..) => AssocSuggestion::AssocFn { called }, ast::AssocItemKind::Type(..) => AssocSuggestion::AssocType, + ast::AssocItemKind::Delegation(..) + if self.r.has_self.contains(&self.r.local_def_id(assoc_item.id)) => + { + AssocSuggestion::MethodWithSelf { called } + } + ast::AssocItemKind::Delegation(..) => AssocSuggestion::AssocFn { called }, ast::AssocItemKind::MacCall(_) => continue, }); } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index a14f3d494fb4d..0adea65ee58ea 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1101,6 +1101,8 @@ pub struct Resolver<'a, 'tcx> { legacy_const_generic_args: FxHashMap>>, /// Amount of lifetime parameters for each item in the crate. item_generics_num_lifetimes: FxHashMap, + /// Amount of parameters for each function in the crate. + fn_parameter_counts: LocalDefIdMap, main_def: Option, trait_impls: FxIndexMap>, @@ -1439,6 +1441,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { doc_link_resolutions: Default::default(), doc_link_traits_in_scope: Default::default(), all_macro_rules: Default::default(), + fn_parameter_counts: Default::default(), }; let root_parent_scope = ParentScope::module(graph_root, &resolver); @@ -1542,6 +1545,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { trait_map: self.trait_map, lifetime_elision_allowed: self.lifetime_elision_allowed, lint_buffer: Steal::new(self.lint_buffer), + has_self: self.has_self, + fn_parameter_counts: self.fn_parameter_counts, }; ResolverOutputs { global_ctxt, ast_lowering } } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 8ed1255c010f1..72b62a795fc50 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -102,6 +102,7 @@ symbols! { Gen: "gen", MacroRules: "macro_rules", Raw: "raw", + Reuse: "reuse", Union: "union", Yeet: "yeet", } diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index 74fa30456eb95..45e8224016466 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -552,7 +552,6 @@ fn handle_reserve(result: Result<(), TryReserveError>) { // `> isize::MAX` bytes will surely fail. On 32-bit and 16-bit we need to add // an extra guard for this in case we're running on a platform which can use // all 4GB in user-space, e.g., PAE or x32. - #[inline] fn alloc_guard(alloc_size: usize) -> Result<(), TryReserveError> { if usize::BITS < 64 && alloc_size > isize::MAX as usize { diff --git a/library/alloc/tests/autotraits.rs b/library/alloc/tests/autotraits.rs index ba5e28f7293e7..6b82deeac8acb 100644 --- a/library/alloc/tests/autotraits.rs +++ b/library/alloc/tests/autotraits.rs @@ -55,12 +55,7 @@ fn test_btree_map() { require_send_sync(async { let _v = None::< - alloc::collections::btree_map::ExtractIf< - '_, - &u32, - &u32, - fn(&&u32, &mut &u32) -> bool, - >, + alloc::collections::btree_map::ExtractIf<'_, &u32, &u32, fn(&&u32, &mut &u32) -> bool>, >; async {}.await; }); diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs index 9ec6f6ae1acd5..0f5e0d99eca12 100644 --- a/library/alloc/tests/vec.rs +++ b/library/alloc/tests/vec.rs @@ -1,7 +1,7 @@ use core::alloc::{Allocator, Layout}; -use core::{assert_eq, assert_ne}; use core::num::NonZeroUsize; use core::ptr::NonNull; +use core::{assert_eq, assert_ne}; use std::alloc::System; use std::assert_matches::assert_matches; use std::borrow::Cow; @@ -1212,7 +1212,7 @@ fn test_in_place_specialization_step_up_down() { assert_eq!(sink.len(), 2); let mut src: Vec<[u8; 3]> = Vec::with_capacity(17); - src.resize( 8, [0; 3]); + src.resize(8, [0; 3]); let iter = src.into_iter().map(|[a, b, _]| [a, b]); assert_in_place_trait(&iter); let sink: Vec<[u8; 2]> = iter.collect(); @@ -1221,11 +1221,7 @@ fn test_in_place_specialization_step_up_down() { let src = vec![[0u8; 4]; 256]; let srcptr = src.as_ptr(); - let iter = src - .into_iter() - .flat_map(|a| { - a.into_iter().map(|b| b.wrapping_add(1)) - }); + let iter = src.into_iter().flat_map(|a| a.into_iter().map(|b| b.wrapping_add(1))); assert_in_place_trait(&iter); let sink = iter.collect::>(); assert_eq!(srcptr as *const u8, sink.as_ptr()); diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 3df3e8ea05cdb..5d917dc6fbb3e 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -1787,8 +1787,9 @@ extern "rust-intrinsic" { /// so this rounds half-way cases to the number with an even least significant digit. /// /// May raise an inexact floating-point exception if the argument is not an integer. - /// However, Rust assumes floating-point exceptions cannot be observed, so this is not something that - /// can actually be used from Rust code. + /// However, Rust assumes floating-point exceptions cannot be observed, so these exceptions + /// cannot actually be utilized from Rust code. + /// In other words, this intrinsic is equivalent in behavior to `nearbyintf32` and `roundevenf32`. /// /// The stabilized version of this intrinsic is /// [`f32::round_ties_even`](../../std/primitive.f32.html#method.round_ties_even) @@ -1798,8 +1799,9 @@ extern "rust-intrinsic" { /// so this rounds half-way cases to the number with an even least significant digit. /// /// May raise an inexact floating-point exception if the argument is not an integer. - /// However, Rust assumes floating-point exceptions cannot be observed, so this is not something that - /// can actually be used from Rust code. + /// However, Rust assumes floating-point exceptions cannot be observed, so these exceptions + /// cannot actually be utilized from Rust code. + /// In other words, this intrinsic is equivalent in behavior to `nearbyintf64` and `roundevenf64`. /// /// The stabilized version of this intrinsic is /// [`f64::round_ties_even`](../../std/primitive.f64.html#method.round_ties_even) diff --git a/library/core/tests/array.rs b/library/core/tests/array.rs index b1c1456ade1ce..ed52de3cbec16 100644 --- a/library/core/tests/array.rs +++ b/library/core/tests/array.rs @@ -1,6 +1,6 @@ -use core::{array, assert_eq}; use core::num::NonZeroUsize; use core::sync::atomic::{AtomicUsize, Ordering}; +use core::{array, assert_eq}; #[test] fn array_from_ref() { diff --git a/library/core/tests/cell.rs b/library/core/tests/cell.rs index 71b8eb296000b..d6a401c2b4d98 100644 --- a/library/core/tests/cell.rs +++ b/library/core/tests/cell.rs @@ -466,14 +466,14 @@ fn const_cells() { const CELL: Cell = Cell::new(3); const _: i32 = CELL.into_inner(); -/* FIXME(#110395) - const UNSAFE_CELL_FROM: UnsafeCell = UnsafeCell::from(3); - const _: i32 = UNSAFE_CELL.into_inner(); + /* FIXME(#110395) + const UNSAFE_CELL_FROM: UnsafeCell = UnsafeCell::from(3); + const _: i32 = UNSAFE_CELL.into_inner(); - const REF_CELL_FROM: RefCell = RefCell::from(3); - const _: i32 = REF_CELL.into_inner(); + const REF_CELL_FROM: RefCell = RefCell::from(3); + const _: i32 = REF_CELL.into_inner(); - const CELL_FROM: Cell = Cell::from(3); - const _: i32 = CELL.into_inner(); -*/ + const CELL_FROM: Cell = Cell::from(3); + const _: i32 = CELL.into_inner(); + */ } diff --git a/library/core/tests/error.rs b/library/core/tests/error.rs index cb7cb5441d1d8..5e20c34ca6ced 100644 --- a/library/core/tests/error.rs +++ b/library/core/tests/error.rs @@ -1,4 +1,4 @@ -use core::error::{request_value, request_ref, Request}; +use core::error::{request_ref, request_value, Request}; // Test the `Request` API. #[derive(Debug)] diff --git a/library/core/tests/fmt/mod.rs b/library/core/tests/fmt/mod.rs index c1c80c46c78b7..704d246139947 100644 --- a/library/core/tests/fmt/mod.rs +++ b/library/core/tests/fmt/mod.rs @@ -22,11 +22,11 @@ fn test_pointer_formats_data_pointer() { #[test] fn test_estimated_capacity() { assert_eq!(format_args!("").estimated_capacity(), 0); - assert_eq!(format_args!("{}", {""}).estimated_capacity(), 0); + assert_eq!(format_args!("{}", { "" }).estimated_capacity(), 0); assert_eq!(format_args!("Hello").estimated_capacity(), 5); - assert_eq!(format_args!("Hello, {}!", {""}).estimated_capacity(), 16); - assert_eq!(format_args!("{}, hello!", {"World"}).estimated_capacity(), 0); - assert_eq!(format_args!("{}. 16-bytes piece", {"World"}).estimated_capacity(), 32); + assert_eq!(format_args!("Hello, {}!", { "" }).estimated_capacity(), 16); + assert_eq!(format_args!("{}, hello!", { "World" }).estimated_capacity(), 0); + assert_eq!(format_args!("{}. 16-bytes piece", { "World" }).estimated_capacity(), 32); } #[test] diff --git a/library/core/tests/hash/mod.rs b/library/core/tests/hash/mod.rs index addc255de4af4..3b9351457a959 100644 --- a/library/core/tests/hash/mod.rs +++ b/library/core/tests/hash/mod.rs @@ -35,7 +35,8 @@ impl Hasher for MyHasher { #[test] fn test_writer_hasher() { // FIXME(#110395) - /* const */ fn hash(t: &T) -> u64 { + /* const */ + fn hash(t: &T) -> u64 { let mut s = MyHasher { hash: 0 }; t.hash(&mut s); s.finish() @@ -140,7 +141,8 @@ impl Hash for Custom { #[test] fn test_custom_state() { // FIXME(#110395) - /* const */ fn hash(t: &T) -> u64 { + /* const */ + fn hash(t: &T) -> u64 { let mut c = CustomHasher { output: 0 }; t.hash(&mut c); c.finish() diff --git a/library/core/tests/iter/adapters/chain.rs b/library/core/tests/iter/adapters/chain.rs index 175a1b638e1a1..ad78a85a88dcb 100644 --- a/library/core/tests/iter/adapters/chain.rs +++ b/library/core/tests/iter/adapters/chain.rs @@ -42,7 +42,10 @@ fn test_iterator_chain_advance_by() { let mut iter = Unfuse::new(xs).chain(Unfuse::new(ys)); assert_eq!(iter.advance_by(xs.len() + i), Ok(())); assert_eq!(iter.next(), Some(&ys[i])); - assert_eq!(iter.advance_by(100), Err(NonZeroUsize::new(100 - (ys.len() - i - 1)).unwrap())); + assert_eq!( + iter.advance_by(100), + Err(NonZeroUsize::new(100 - (ys.len() - i - 1)).unwrap()) + ); assert_eq!(iter.advance_by(0), Ok(())); } @@ -71,7 +74,10 @@ fn test_iterator_chain_advance_back_by() { let mut iter = Unfuse::new(xs).chain(Unfuse::new(ys)); assert_eq!(iter.advance_back_by(i), Ok(())); assert_eq!(iter.next_back(), Some(&ys[ys.len() - i - 1])); - assert_eq!(iter.advance_back_by(100), Err(NonZeroUsize::new(100 - (len - i - 1)).unwrap())); + assert_eq!( + iter.advance_back_by(100), + Err(NonZeroUsize::new(100 - (len - i - 1)).unwrap()) + ); assert_eq!(iter.advance_back_by(0), Ok(())); } @@ -79,7 +85,10 @@ fn test_iterator_chain_advance_back_by() { let mut iter = Unfuse::new(xs).chain(Unfuse::new(ys)); assert_eq!(iter.advance_back_by(ys.len() + i), Ok(())); assert_eq!(iter.next_back(), Some(&xs[xs.len() - i - 1])); - assert_eq!(iter.advance_back_by(100), Err(NonZeroUsize::new(100 - (xs.len() - i - 1)).unwrap())); + assert_eq!( + iter.advance_back_by(100), + Err(NonZeroUsize::new(100 - (xs.len() - i - 1)).unwrap()) + ); assert_eq!(iter.advance_back_by(0), Ok(())); } diff --git a/library/core/tests/iter/adapters/flatten.rs b/library/core/tests/iter/adapters/flatten.rs index 91809c9e5fd5d..f429d90cd7ddd 100644 --- a/library/core/tests/iter/adapters/flatten.rs +++ b/library/core/tests/iter/adapters/flatten.rs @@ -1,5 +1,5 @@ -use core::assert_eq; use super::*; +use core::assert_eq; use core::iter::*; use core::num::NonZeroUsize; diff --git a/library/core/tests/iter/adapters/step_by.rs b/library/core/tests/iter/adapters/step_by.rs index 4c5b1dd9a6bd1..70c9906163ae8 100644 --- a/library/core/tests/iter/adapters/step_by.rs +++ b/library/core/tests/iter/adapters/step_by.rs @@ -245,7 +245,6 @@ fn test_step_by_skip() { assert_eq!((200..=255u8).step_by(10).nth(3), Some(230)); } - struct DeOpt(I); impl Iterator for DeOpt { @@ -265,17 +264,15 @@ impl DoubleEndedIterator for DeOpt { #[test] fn test_step_by_fold_range_specialization() { macro_rules! t { - ($range:expr, $var: ident, $body:tt) => { - { - // run the same tests for the non-optimized version - let mut $var = DeOpt($range); - $body - } - { - let mut $var = $range; - $body - } + ($range:expr, $var: ident, $body:tt) => {{ + // run the same tests for the non-optimized version + let mut $var = DeOpt($range); + $body } + { + let mut $var = $range; + $body + }}; } t!((1usize..5).step_by(1), r, { @@ -288,13 +285,12 @@ fn test_step_by_fold_range_specialization() { assert_eq!(r.sum::(), 2); }); - t!((0usize..5).step_by(2), r, { assert_eq!(r.next(), Some(0)); assert_eq!(r.sum::(), 6); }); - t!((usize::MAX - 6 .. usize::MAX).step_by(5), r, { + t!((usize::MAX - 6..usize::MAX).step_by(5), r, { assert_eq!(r.next(), Some(usize::MAX - 6)); assert_eq!(r.sum::(), usize::MAX - 1); }); diff --git a/library/core/tests/iter/adapters/take.rs b/library/core/tests/iter/adapters/take.rs index 3cad47c06de03..ff6e362b065c6 100644 --- a/library/core/tests/iter/adapters/take.rs +++ b/library/core/tests/iter/adapters/take.rs @@ -93,7 +93,10 @@ fn test_take_advance_by() { assert_eq!((0..2).take(1).advance_back_by(10), Err(NonZeroUsize::new(9).unwrap())); assert_eq!((0..0).take(1).advance_back_by(1), Err(NonZeroUsize::new(1).unwrap())); assert_eq!((0..0).take(1).advance_back_by(0), Ok(())); - assert_eq!((0..usize::MAX).take(100).advance_back_by(usize::MAX), Err(NonZeroUsize::new(usize::MAX - 100).unwrap())); + assert_eq!( + (0..usize::MAX).take(100).advance_back_by(usize::MAX), + Err(NonZeroUsize::new(usize::MAX - 100).unwrap()) + ); } #[test] diff --git a/library/core/tests/iter/adapters/zip.rs b/library/core/tests/iter/adapters/zip.rs index c3508be8598fb..ba54de5822bf7 100644 --- a/library/core/tests/iter/adapters/zip.rs +++ b/library/core/tests/iter/adapters/zip.rs @@ -184,7 +184,7 @@ fn test_zip_nested_sideffectful() { let it = xs.iter_mut().map(|x| *x = 1).enumerate().zip(&ys); it.count(); } - let length_aware = &xs == &[1, 1, 1, 1, 0, 0]; + let length_aware = &xs == &[1, 1, 1, 1, 0, 0]; let probe_first = &xs == &[1, 1, 1, 1, 1, 0]; // either implementation is valid according to zip documentation diff --git a/library/core/tests/iter/traits/iterator.rs b/library/core/tests/iter/traits/iterator.rs index 995bbf0e26156..9c1dce7b66dff 100644 --- a/library/core/tests/iter/traits/iterator.rs +++ b/library/core/tests/iter/traits/iterator.rs @@ -168,7 +168,10 @@ fn test_iterator_advance_back_by() { let mut iter = v.iter(); assert_eq!(iter.advance_back_by(i), Ok(())); assert_eq!(iter.next_back().unwrap(), &v[v.len() - 1 - i]); - assert_eq!(iter.advance_back_by(100), Err(NonZeroUsize::new(100 - (v.len() - 1 - i)).unwrap())); + assert_eq!( + iter.advance_back_by(100), + Err(NonZeroUsize::new(100 - (v.len() - 1 - i)).unwrap()) + ); } assert_eq!(v.iter().advance_back_by(v.len()), Ok(())); @@ -183,7 +186,10 @@ fn test_iterator_rev_advance_back_by() { let mut iter = v.iter().rev(); assert_eq!(iter.advance_back_by(i), Ok(())); assert_eq!(iter.next_back().unwrap(), &v[i]); - assert_eq!(iter.advance_back_by(100), Err(NonZeroUsize::new(100 - (v.len() - 1 - i)).unwrap())); + assert_eq!( + iter.advance_back_by(100), + Err(NonZeroUsize::new(100 - (v.len() - 1 - i)).unwrap()) + ); } assert_eq!(v.iter().rev().advance_back_by(v.len()), Ok(())); diff --git a/library/core/tests/net/ip_addr.rs b/library/core/tests/net/ip_addr.rs index 7f7802c221a61..3d13bffba92af 100644 --- a/library/core/tests/net/ip_addr.rs +++ b/library/core/tests/net/ip_addr.rs @@ -664,7 +664,11 @@ fn ipv6_properties() { &[0x20, 1, 0, 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], global | unicast_global ); - check!("2001:30::", &[0x20, 1, 0, 0x30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], global | unicast_global); + check!( + "2001:30::", + &[0x20, 1, 0, 0x30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + global | unicast_global + ); check!("2001:40::", &[0x20, 1, 0, 0x40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unicast_global); check!( diff --git a/library/core/tests/option.rs b/library/core/tests/option.rs index 00a308b29d250..b1b9492f182e0 100644 --- a/library/core/tests/option.rs +++ b/library/core/tests/option.rs @@ -178,19 +178,19 @@ fn test_or_else() { assert_eq!(x.or_else(two), Some(2)); assert_eq!(x.or_else(none), None); -/* FIXME(#110395) - const FOO: Option = Some(1); - const A: Option = FOO.or_else(two); - const B: Option = FOO.or_else(none); - assert_eq!(A, Some(1)); - assert_eq!(B, Some(1)); - - const BAR: Option = None; - const C: Option = BAR.or_else(two); - const D: Option = BAR.or_else(none); - assert_eq!(C, Some(2)); - assert_eq!(D, None); -*/ + /* FIXME(#110395) + const FOO: Option = Some(1); + const A: Option = FOO.or_else(two); + const B: Option = FOO.or_else(none); + assert_eq!(A, Some(1)); + assert_eq!(B, Some(1)); + + const BAR: Option = None; + const C: Option = BAR.or_else(two); + const D: Option = BAR.or_else(none); + assert_eq!(C, Some(2)); + assert_eq!(D, None); + */ } #[test] @@ -486,15 +486,15 @@ const fn option_const_mut() { None => unreachable!(), } } -/* FIXME(const-hack) - { - let as_mut: Option<&mut usize> = Option::from(&mut option); - match as_mut { - Some(v) => *v = 42, - None => unreachable!(), + /* FIXME(const-hack) + { + let as_mut: Option<&mut usize> = Option::from(&mut option); + match as_mut { + Some(v) => *v = 42, + None => unreachable!(), + } } - } -*/ + */ } #[test] diff --git a/library/core/tests/ptr.rs b/library/core/tests/ptr.rs index 238f29c598043..b68f2a50b3211 100644 --- a/library/core/tests/ptr.rs +++ b/library/core/tests/ptr.rs @@ -478,7 +478,11 @@ fn align_offset_various_strides() { x |= test_stride::(ptr::invalid::(ptr), align); #[repr(packed)] - struct A10(#[allow(dead_code)] u32, #[allow(dead_code)] u32, #[allow(dead_code)] u16); + struct A10( + #[allow(dead_code)] u32, + #[allow(dead_code)] u32, + #[allow(dead_code)] u16, + ); x |= test_stride::(ptr::invalid::(ptr), align); x |= test_stride::(ptr::invalid::(ptr), align); @@ -532,7 +536,11 @@ fn align_offset_various_strides_const() { test_stride::(ptr::invalid::(ptr), ptr, align); #[repr(packed)] - struct A7(#[allow(dead_code)] u32, #[allow(dead_code)] u16, #[allow(dead_code)] u8); + struct A7( + #[allow(dead_code)] u32, + #[allow(dead_code)] u16, + #[allow(dead_code)] u8, + ); test_stride::(ptr::invalid::(ptr), ptr, align); #[repr(packed)] @@ -540,11 +548,19 @@ fn align_offset_various_strides_const() { test_stride::(ptr::invalid::(ptr), ptr, align); #[repr(packed)] - struct A9(#[allow(dead_code)] u32, #[allow(dead_code)] u32, #[allow(dead_code)] u8); + struct A9( + #[allow(dead_code)] u32, + #[allow(dead_code)] u32, + #[allow(dead_code)] u8, + ); test_stride::(ptr::invalid::(ptr), ptr, align); #[repr(packed)] - struct A10(#[allow(dead_code)] u32, #[allow(dead_code)] u32, #[allow(dead_code)] u16); + struct A10( + #[allow(dead_code)] u32, + #[allow(dead_code)] u32, + #[allow(dead_code)] u16, + ); test_stride::(ptr::invalid::(ptr), ptr, align); test_stride::(ptr::invalid::(ptr), ptr, align); diff --git a/library/core/tests/time.rs b/library/core/tests/time.rs index 24ab4be9d8c9f..23f07bf84b3db 100644 --- a/library/core/tests/time.rs +++ b/library/core/tests/time.rs @@ -479,22 +479,22 @@ fn duration_const() { const CHECKED_MUL: Option = Duration::SECOND.checked_mul(1); assert_eq!(CHECKED_MUL, Some(Duration::SECOND)); -/* FIXME(#110395) - const MUL_F32: Duration = Duration::SECOND.mul_f32(1.0); - assert_eq!(MUL_F32, Duration::SECOND); + /* FIXME(#110395) + const MUL_F32: Duration = Duration::SECOND.mul_f32(1.0); + assert_eq!(MUL_F32, Duration::SECOND); - const MUL_F64: Duration = Duration::SECOND.mul_f64(1.0); - assert_eq!(MUL_F64, Duration::SECOND); + const MUL_F64: Duration = Duration::SECOND.mul_f64(1.0); + assert_eq!(MUL_F64, Duration::SECOND); - const CHECKED_DIV: Option = Duration::SECOND.checked_div(1); - assert_eq!(CHECKED_DIV, Some(Duration::SECOND)); + const CHECKED_DIV: Option = Duration::SECOND.checked_div(1); + assert_eq!(CHECKED_DIV, Some(Duration::SECOND)); - const DIV_F32: Duration = Duration::SECOND.div_f32(1.0); - assert_eq!(DIV_F32, Duration::SECOND); + const DIV_F32: Duration = Duration::SECOND.div_f32(1.0); + assert_eq!(DIV_F32, Duration::SECOND); - const DIV_F64: Duration = Duration::SECOND.div_f64(1.0); - assert_eq!(DIV_F64, Duration::SECOND); -*/ + const DIV_F64: Duration = Duration::SECOND.div_f64(1.0); + assert_eq!(DIV_F64, Duration::SECOND); + */ const DIV_DURATION_F32: f32 = Duration::SECOND.div_duration_f32(Duration::SECOND); assert_eq!(DIV_DURATION_F32, 1.0); diff --git a/library/std/tests/process_spawning.rs b/library/std/tests/process_spawning.rs index 46dc9ff00bd0d..59f67f9901ffa 100644 --- a/library/std/tests/process_spawning.rs +++ b/library/std/tests/process_spawning.rs @@ -1,4 +1,4 @@ -#![cfg(not(target_env="sgx"))] +#![cfg(not(target_env = "sgx"))] use std::env; use std::fs; diff --git a/rustfmt.toml b/rustfmt.toml index e292a3107420e..e6cc298ec44c6 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -13,7 +13,7 @@ ignore = [ # tests for now are not formatted, as they are sometimes pretty-printing constrained # (and generally rustfmt can move around comments in UI-testing incompatible ways) - "tests", + "/tests/", # do not format submodules # FIXME: sync submodule list with tidy/bootstrap/etc diff --git a/src/bootstrap/src/tests/config.rs b/src/bootstrap/src/tests/config.rs index 6f43234388266..c65067f8e8f76 100644 --- a/src/bootstrap/src/tests/config.rs +++ b/src/bootstrap/src/tests/config.rs @@ -32,9 +32,12 @@ fn download_ci_llvm() { assert_eq!(parse_llvm("rust.channel = \"dev\""), if_unchanged); assert!(!parse_llvm("rust.channel = \"stable\"")); assert_eq!(parse_llvm("build.build = \"x86_64-unknown-linux-gnu\""), if_unchanged); - assert_eq!(parse_llvm( - "llvm.assertions = true \r\n build.build = \"x86_64-unknown-linux-gnu\" \r\n llvm.download-ci-llvm = \"if-unchanged\"" - ), if_unchanged); + assert_eq!( + parse_llvm( + "llvm.assertions = true \r\n build.build = \"x86_64-unknown-linux-gnu\" \r\n llvm.download-ci-llvm = \"if-unchanged\"" + ), + if_unchanged + ); assert!(!parse_llvm( "llvm.assertions = true \r\n build.build = \"aarch64-apple-darwin\" \r\n llvm.download-ci-llvm = \"if-unchanged\"" )); diff --git a/src/bootstrap/src/tests/helpers.rs b/src/bootstrap/src/tests/helpers.rs index 163594dbb2f14..2d626fad417d7 100644 --- a/src/bootstrap/src/tests/helpers.rs +++ b/src/bootstrap/src/tests/helpers.rs @@ -1,4 +1,4 @@ -use crate::utils::helpers::{extract_beta_rev, hex_encode, make, check_cfg_arg}; +use crate::utils::helpers::{check_cfg_arg, extract_beta_rev, hex_encode, make}; use std::path::PathBuf; #[test] diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 9c0a8634990b3..124a2d9cba957 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1870,7 +1870,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T } TyKind::BareFn(barefn) => BareFunction(Box::new(clean_bare_fn_ty(barefn, cx))), // Rustdoc handles `TyKind::Err`s by turning them into `Type::Infer`s. - TyKind::Infer | TyKind::Err(_) | TyKind::Typeof(..) => Infer, + TyKind::Infer | TyKind::Err(_) | TyKind::Typeof(..) | TyKind::InferDelegation(..) => Infer, } } diff --git a/src/librustdoc/clean/render_macro_matchers.rs b/src/librustdoc/clean/render_macro_matchers.rs index 605f9e496c769..b736f4a795614 100644 --- a/src/librustdoc/clean/render_macro_matchers.rs +++ b/src/librustdoc/clean/render_macro_matchers.rs @@ -69,8 +69,8 @@ fn snippet_equal_to_token(tcx: TyCtxt<'_>, matcher: &TokenTree) -> Option parser, - Err(diagnostics) => { - drop(diagnostics); + Err(errs) => { + errs.into_iter().for_each(|err| err.cancel()); return None; } }; diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 9a9006252684d..82746a7ab0343 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -589,7 +589,7 @@ pub(crate) fn make_test( let mut parser = match maybe_new_parser_from_source_str(&sess, filename, source) { Ok(p) => p, Err(errs) => { - drop(errs); + errs.into_iter().for_each(|err| err.cancel()); return (found_main, found_extern_crate, found_macro); } }; @@ -759,8 +759,10 @@ fn check_if_attr_is_complete(source: &str, edition: Edition) -> bool { let mut parser = match maybe_new_parser_from_source_str(&sess, filename, source.to_owned()) { Ok(p) => p, - Err(_) => { - // If there is an unclosed delimiter, an error will be returned by the tokentrees. + Err(errs) => { + errs.into_iter().for_each(|err| err.cancel()); + // If there is an unclosed delimiter, an error will be returned by the + // tokentrees. return false; } }; diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs index aaef163ad554b..8ff54dfcfa0dc 100644 --- a/src/tools/clippy/clippy_lints/src/dereference.rs +++ b/src/tools/clippy/clippy_lints/src/dereference.rs @@ -830,6 +830,7 @@ impl TyCoercionStability { | TyKind::Infer | TyKind::Typeof(..) | TyKind::TraitObject(..) + | TyKind::InferDelegation(..) | TyKind::Err(_) => Self::Reborrow, }; } diff --git a/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs b/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs index a744b69ecb478..8b018220c1715 100644 --- a/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs +++ b/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs @@ -53,7 +53,7 @@ pub fn check( let mut parser = match maybe_new_parser_from_source_str(&sess, filename, code) { Ok(p) => p, Err(errs) => { - drop(errs); + errs.into_iter().for_each(|err| err.cancel()); return (false, test_attr_spans); }, }; diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index a23105691bf3b..43816c9abac3c 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -1108,7 +1108,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { TyKind::Typeof(anon_const) => { self.hash_body(anon_const.body); }, - TyKind::Err(_) | TyKind::Infer | TyKind::Never => {}, + TyKind::Err(_) | TyKind::Infer | TyKind::Never | TyKind::InferDelegation(..) => {}, } } diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs index 6fb69d6b88393..b57be8c10549e 100644 --- a/src/tools/rustfmt/src/items.rs +++ b/src/tools/rustfmt/src/items.rs @@ -728,7 +728,9 @@ impl<'a> FmtVisitor<'a> { (Const(..), Const(..)) | (MacCall(..), MacCall(..)) => { a.ident.as_str().cmp(b.ident.as_str()) } - (Fn(..), Fn(..)) => a.span.lo().cmp(&b.span.lo()), + (Fn(..), Fn(..)) | (Delegation(..), Delegation(..)) => { + a.span.lo().cmp(&b.span.lo()) + } (Type(ty), _) if is_type(&ty.ty) => Ordering::Less, (_, Type(ty)) if is_type(&ty.ty) => Ordering::Greater, (Type(..), _) => Ordering::Less, @@ -737,6 +739,8 @@ impl<'a> FmtVisitor<'a> { (_, Const(..)) => Ordering::Greater, (MacCall(..), _) => Ordering::Less, (_, MacCall(..)) => Ordering::Greater, + (Delegation(..), _) => Ordering::Less, + (_, Delegation(..)) => Ordering::Greater, }); let mut prev_kind = None; for (buf, item) in buffer { diff --git a/src/tools/rustfmt/src/parse/parser.rs b/src/tools/rustfmt/src/parse/parser.rs index 7045a7dd9ce35..31226cf8c307d 100644 --- a/src/tools/rustfmt/src/parse/parser.rs +++ b/src/tools/rustfmt/src/parse/parser.rs @@ -3,7 +3,7 @@ use std::path::{Path, PathBuf}; use rustc_ast::token::TokenKind; use rustc_ast::{ast, attr, ptr}; -use rustc_errors::Diagnostic; +use rustc_errors::DiagnosticBuilder; use rustc_parse::{new_parser_from_file, parser::Parser as RawParser}; use rustc_span::{sym, Span}; use thin_vec::ThinVec; @@ -65,7 +65,7 @@ impl<'a> ParserBuilder<'a> { fn parser( sess: &'a rustc_session::parse::ParseSess, input: Input, - ) -> Result, Option>> { + ) -> Result, Option>>> { match input { Input::File(ref file) => catch_unwind(AssertUnwindSafe(move || { new_parser_from_file(sess, file, None) diff --git a/src/tools/rustfmt/src/parse/session.rs b/src/tools/rustfmt/src/parse/session.rs index f4fb5073dfdcd..6dc3eac44d43d 100644 --- a/src/tools/rustfmt/src/parse/session.rs +++ b/src/tools/rustfmt/src/parse/session.rs @@ -4,7 +4,9 @@ use std::sync::atomic::{AtomicBool, Ordering}; use rustc_data_structures::sync::{IntoDynSyncSend, Lrc}; use rustc_errors::emitter::{DynEmitter, Emitter, HumanEmitter}; use rustc_errors::translation::Translate; -use rustc_errors::{ColorConfig, DiagCtxt, Diagnostic, Level as DiagnosticLevel}; +use rustc_errors::{ + ColorConfig, DiagCtxt, Diagnostic, DiagnosticBuilder, Level as DiagnosticLevel, +}; use rustc_session::parse::ParseSess as RawParseSess; use rustc_span::{ source_map::{FilePathMapping, SourceMap}, @@ -283,9 +285,9 @@ impl ParseSess { // Methods that should be restricted within the parse module. impl ParseSess { - pub(super) fn emit_diagnostics(&self, diagnostics: Vec) { + pub(super) fn emit_diagnostics(&self, diagnostics: Vec>) { for diagnostic in diagnostics { - self.parse_sess.dcx.emit_diagnostic(diagnostic); + diagnostic.emit(); } } diff --git a/src/tools/rustfmt/src/visitor.rs b/src/tools/rustfmt/src/visitor.rs index f4d84d1381fc0..bc5accefd92b8 100644 --- a/src/tools/rustfmt/src/visitor.rs +++ b/src/tools/rustfmt/src/visitor.rs @@ -592,6 +592,11 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ); self.push_rewrite(item.span, rewrite); } + ast::ItemKind::Delegation(..) => { + // TODO: rewrite delegation items once syntax is established. + // For now, leave the contents of the Span unformatted. + self.push_rewrite(item.span, None) + } }; } self.skip_context = skip_context_saved; diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 62d48315d434e..c198c116282bd 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -194,6 +194,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "aho-corasick", "allocator-api2", // FIXME: only appears in Cargo.lock due to https://github.com/rust-lang/cargo/issues/10801 "annotate-snippets", + "anstyle", "ar_archive_writer", "arrayvec", "autocfg", @@ -391,7 +392,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "windows_x86_64_gnullvm", "windows_x86_64_msvc", "writeable", - "yansi-term", // this is a false-positive: it's only used by rustfmt, but because it's enabled through a feature, tidy thinks it's used by rustc as well. "yoke", "yoke-derive", "zerocopy", diff --git a/tests/mir-opt/instrument_coverage.bar.InstrumentCoverage.diff b/tests/mir-opt/instrument_coverage.bar.InstrumentCoverage.diff index 1ef6b69ef5b0c..dec99ff4601a0 100644 --- a/tests/mir-opt/instrument_coverage.bar.InstrumentCoverage.diff +++ b/tests/mir-opt/instrument_coverage.bar.InstrumentCoverage.diff @@ -4,7 +4,7 @@ fn bar() -> bool { let mut _0: bool; -+ coverage Counter(0) => /the/src/instrument_coverage.rs:21:1 - 23:2; ++ coverage Code(Counter(0)) => /the/src/instrument_coverage.rs:21:1 - 23:2; + bb0: { + Coverage::CounterIncrement(0); diff --git a/tests/mir-opt/instrument_coverage.main.InstrumentCoverage.diff b/tests/mir-opt/instrument_coverage.main.InstrumentCoverage.diff index 14b4833a515b6..368088d12961a 100644 --- a/tests/mir-opt/instrument_coverage.main.InstrumentCoverage.diff +++ b/tests/mir-opt/instrument_coverage.main.InstrumentCoverage.diff @@ -9,11 +9,11 @@ + coverage ExpressionId(0) => Expression { lhs: Counter(0), op: Add, rhs: Counter(1) }; + coverage ExpressionId(1) => Expression { lhs: Expression(0), op: Subtract, rhs: Counter(1) }; -+ coverage Counter(0) => /the/src/instrument_coverage.rs:12:1 - 12:11; -+ coverage Expression(0) => /the/src/instrument_coverage.rs:13:5 - 14:17; -+ coverage Expression(1) => /the/src/instrument_coverage.rs:15:13 - 15:18; -+ coverage Expression(1) => /the/src/instrument_coverage.rs:18:1 - 18:2; -+ coverage Counter(1) => /the/src/instrument_coverage.rs:16:10 - 16:11; ++ coverage Code(Counter(0)) => /the/src/instrument_coverage.rs:12:1 - 12:11; ++ coverage Code(Expression(0)) => /the/src/instrument_coverage.rs:13:5 - 14:17; ++ coverage Code(Expression(1)) => /the/src/instrument_coverage.rs:15:13 - 15:18; ++ coverage Code(Counter(1)) => /the/src/instrument_coverage.rs:16:10 - 16:11; ++ coverage Code(Expression(1)) => /the/src/instrument_coverage.rs:18:1 - 18:2; + bb0: { + Coverage::CounterIncrement(0); diff --git a/tests/pretty/delegation.rs b/tests/pretty/delegation.rs new file mode 100644 index 0000000000000..6a46437f7d638 --- /dev/null +++ b/tests/pretty/delegation.rs @@ -0,0 +1,25 @@ +#![feature(fn_delegation)] +//~^ WARN the feature `fn_delegation` is incomplete + +// pp-exact + +trait Trait { + fn bar(&self, x: i32) -> i32 { x } +} + +struct F; +impl Trait for F {} + +struct S(F); +impl Trait for S { + reuse Trait::bar { &self.0 } +} + +mod to_reuse { + pub fn foo() {} +} + +#[inline] +pub reuse to_reuse::foo; + +fn main() {} diff --git a/tests/rustdoc-ui/ice-bug-report-url.stderr b/tests/rustdoc-ui/ice-bug-report-url.stderr index 869fcd20fac8e..06a5269131083 100644 --- a/tests/rustdoc-ui/ice-bug-report-url.stderr +++ b/tests/rustdoc-ui/ice-bug-report-url.stderr @@ -1,4 +1,4 @@ -error: expected one of `->`, `where`, or `{`, found `` +error: internal compiler error: expected one of `->`, `where`, or `{`, found `` --> $DIR/ice-bug-report-url.rs:14:10 | LL | fn wrong() diff --git a/tests/rustdoc-ui/unable-fulfill-trait.rs b/tests/rustdoc-ui/unable-fulfill-trait.rs index 10887ab190302..a69f74b09ac04 100644 --- a/tests/rustdoc-ui/unable-fulfill-trait.rs +++ b/tests/rustdoc-ui/unable-fulfill-trait.rs @@ -4,7 +4,6 @@ pub struct Foo<'a, 'b, T> { field1: dyn Bar<'a, 'b,>, //~^ ERROR //~| ERROR - //~| ERROR } pub trait Bar<'x, 's, U> diff --git a/tests/rustdoc-ui/unable-fulfill-trait.stderr b/tests/rustdoc-ui/unable-fulfill-trait.stderr index d7735a4fd1127..72f35cb922445 100644 --- a/tests/rustdoc-ui/unable-fulfill-trait.stderr +++ b/tests/rustdoc-ui/unable-fulfill-trait.stderr @@ -5,7 +5,7 @@ LL | field1: dyn Bar<'a, 'b,>, | ^^^ expected 1 generic argument | note: trait defined here, with 1 generic parameter: `U` - --> $DIR/unable-fulfill-trait.rs:10:11 + --> $DIR/unable-fulfill-trait.rs:9:11 | LL | pub trait Bar<'x, 's, U> | ^^^ - @@ -20,24 +20,7 @@ error[E0227]: ambiguous lifetime bound, explicit lifetime bound required LL | field1: dyn Bar<'a, 'b,>, | ^^^^^^^^^^^^^^^^ -error[E0478]: lifetime bound not satisfied - --> $DIR/unable-fulfill-trait.rs:4:13 - | -LL | field1: dyn Bar<'a, 'b,>, - | ^^^^^^^^^^^^^^^^ - | -note: lifetime parameter instantiated with the lifetime `'b` as defined here - --> $DIR/unable-fulfill-trait.rs:3:20 - | -LL | pub struct Foo<'a, 'b, T> { - | ^^ -note: but lifetime parameter must outlive the lifetime `'a` as defined here - --> $DIR/unable-fulfill-trait.rs:3:16 - | -LL | pub struct Foo<'a, 'b, T> { - | ^^ - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0107, E0227, E0478. +Some errors have detailed explanations: E0107, E0227. For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/associated-inherent-types/issue-109071.no_gate.stderr b/tests/ui/associated-inherent-types/issue-109071.no_gate.stderr index 3acec9c085a25..e3eddf489b04e 100644 --- a/tests/ui/associated-inherent-types/issue-109071.no_gate.stderr +++ b/tests/ui/associated-inherent-types/issue-109071.no_gate.stderr @@ -30,7 +30,7 @@ LL | type Item = &[T]; = help: add `#![feature(inherent_associated_types)]` to the crate attributes to enable error[E0223]: ambiguous associated type - --> $DIR/issue-109071.rs:16:22 + --> $DIR/issue-109071.rs:15:22 | LL | fn T() -> Option {} | ^^^^^^^^^^ diff --git a/tests/ui/associated-inherent-types/issue-109071.rs b/tests/ui/associated-inherent-types/issue-109071.rs index a897aaebc58f3..cbe8cce092457 100644 --- a/tests/ui/associated-inherent-types/issue-109071.rs +++ b/tests/ui/associated-inherent-types/issue-109071.rs @@ -9,13 +9,11 @@ impl Windows { //~ ERROR: missing generics for struct `Windows` //[no_gate]~^ ERROR: inherent associated types are unstable fn next() -> Option {} - //[with_gate]~^ ERROR type annotations needed } impl Windows { fn T() -> Option {} - //[no_gate]~^ ERROR: ambiguous associated type - //[with_gate]~^^ ERROR type annotations needed + //~^ ERROR: ambiguous associated type } fn main() {} diff --git a/tests/ui/associated-inherent-types/issue-109071.with_gate.stderr b/tests/ui/associated-inherent-types/issue-109071.with_gate.stderr index d413c65dccb53..a7d17e2d5ebb9 100644 --- a/tests/ui/associated-inherent-types/issue-109071.with_gate.stderr +++ b/tests/ui/associated-inherent-types/issue-109071.with_gate.stderr @@ -20,19 +20,20 @@ help: add missing generic argument LL | impl Windows { | +++ -error[E0282]: type annotations needed - --> $DIR/issue-109071.rs:11:18 - | -LL | fn next() -> Option {} - | ^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T` - -error[E0282]: type annotations needed - --> $DIR/issue-109071.rs:16:15 +error[E0223]: ambiguous associated type + --> $DIR/issue-109071.rs:15:22 | LL | fn T() -> Option {} - | ^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T` + | ^^^^^^^^^^ + | +help: use fully-qualified syntax + | +LL | fn T() -> Option< as IntoAsyncIterator>::Item> {} + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +LL | fn T() -> Option< as IntoIterator>::Item> {} + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0107, E0282, E0637. +Some errors have detailed explanations: E0107, E0223, E0637. For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/associated-types/issue-23595-1.rs b/tests/ui/associated-types/issue-23595-1.rs index 9222f5b66509b..579fde34f53b4 100644 --- a/tests/ui/associated-types/issue-23595-1.rs +++ b/tests/ui/associated-types/issue-23595-1.rs @@ -5,9 +5,8 @@ use std::ops::Index; trait Hierarchy { type Value; type ChildKey; - type Children = dyn Index; + type Children = dyn Index; //~^ ERROR: the value of the associated types - //~| ERROR: the size for values of type fn data(&self) -> Option<(Self::Value, Self::Children)>; } diff --git a/tests/ui/associated-types/issue-23595-1.stderr b/tests/ui/associated-types/issue-23595-1.stderr index 46906ab3fb7a1..694b68ef0901a 100644 --- a/tests/ui/associated-types/issue-23595-1.stderr +++ b/tests/ui/associated-types/issue-23595-1.stderr @@ -1,27 +1,13 @@ error[E0191]: the value of the associated types `Value`, `ChildKey` and `Children` in `Hierarchy` must be specified - --> $DIR/issue-23595-1.rs:8:58 + --> $DIR/issue-23595-1.rs:8:60 | LL | type Value; | ---------- `Value` defined here LL | type ChildKey; | ------------- `ChildKey` defined here -LL | type Children = dyn Index; - | ------------- `Children` defined here ^^^^^^^^^ help: specify the associated types: `Hierarchy` +LL | type Children = dyn Index; + | ------------- `Children` defined here ^^^^^^^^^ help: specify the associated types: `Hierarchy` -error[E0277]: the size for values of type `(dyn Index<::ChildKey, Output = (dyn Hierarchy + 'static)> + 'static)` cannot be known at compilation time - --> $DIR/issue-23595-1.rs:8:21 - | -LL | type Children = dyn Index; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for `(dyn Index<::ChildKey, Output = (dyn Hierarchy + 'static)> + 'static)` -note: required by a bound in `Hierarchy::Children` - --> $DIR/issue-23595-1.rs:8:5 - | -LL | type Children = dyn Index; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Hierarchy::Children` - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0191, E0277. -For more information about an error, try `rustc --explain E0191`. +For more information about this error, try `rustc --explain E0191`. diff --git a/tests/ui/const-generics/issues/issue-71381.full.stderr b/tests/ui/const-generics/issues/issue-71381.full.stderr index b6460e0017fa5..5d7800746961b 100644 --- a/tests/ui/const-generics/issues/issue-71381.full.stderr +++ b/tests/ui/const-generics/issues/issue-71381.full.stderr @@ -7,7 +7,7 @@ LL | pub fn call_me $DIR/issue-71381.rs:23:40 + --> $DIR/issue-71381.rs:22:40 | LL | const FN: unsafe extern "C" fn(Args), | ^^^^ the type must not depend on the parameter `Args` diff --git a/tests/ui/const-generics/issues/issue-71381.min.stderr b/tests/ui/const-generics/issues/issue-71381.min.stderr index e16d3b7a8a469..5d7800746961b 100644 --- a/tests/ui/const-generics/issues/issue-71381.min.stderr +++ b/tests/ui/const-generics/issues/issue-71381.min.stderr @@ -7,29 +7,13 @@ LL | pub fn call_me $DIR/issue-71381.rs:23:40 + --> $DIR/issue-71381.rs:22:40 | LL | const FN: unsafe extern "C" fn(Args), | ^^^^ the type must not depend on the parameter `Args` | = note: type parameters may not be used in the type of const parameters -error: using function pointers as const generic parameters is forbidden - --> $DIR/issue-71381.rs:14:61 - | -LL | pub fn call_me(&self) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: the only supported types are integers, `bool` and `char` - -error: using function pointers as const generic parameters is forbidden - --> $DIR/issue-71381.rs:23:19 - | -LL | const FN: unsafe extern "C" fn(Args), - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: the only supported types are integers, `bool` and `char` - -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0770`. diff --git a/tests/ui/const-generics/issues/issue-71381.rs b/tests/ui/const-generics/issues/issue-71381.rs index 8a878efb42a0e..75ad4545371a7 100644 --- a/tests/ui/const-generics/issues/issue-71381.rs +++ b/tests/ui/const-generics/issues/issue-71381.rs @@ -12,8 +12,7 @@ unsafe extern "C" fn pass(args: PassArg) { impl Test { pub fn call_me(&self) { - //[min]~^ ERROR: using function pointers as const generic parameters is forbidden - //~^^ ERROR: the type of const parameters must not depend on other generic parameters + //~^ ERROR: the type of const parameters must not depend on other generic parameters self.0 = Self::trampiline:: as _ } @@ -21,8 +20,7 @@ impl Test { Args: Sized, const IDX: usize, const FN: unsafe extern "C" fn(Args), - //[min]~^ ERROR: using function pointers as const generic parameters is forbidden - //~^^ ERROR: the type of const parameters must not depend on other generic parameters + //~^ ERROR: the type of const parameters must not depend on other generic parameters >( args: Args, ) { diff --git a/tests/ui/const-generics/issues/issue-71611.min.stderr b/tests/ui/const-generics/issues/issue-71611.min.stderr index b01936f4d2513..6f6a9fc21a699 100644 --- a/tests/ui/const-generics/issues/issue-71611.min.stderr +++ b/tests/ui/const-generics/issues/issue-71611.min.stderr @@ -6,14 +6,6 @@ LL | fn func(outer: A) { | = note: type parameters may not be used in the type of const parameters -error: using function pointers as const generic parameters is forbidden - --> $DIR/issue-71611.rs:5:21 - | -LL | fn func(outer: A) { - | ^^^^^^^^^^^^ - | - = note: the only supported types are integers, `bool` and `char` - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0770`. diff --git a/tests/ui/const-generics/issues/issue-71611.rs b/tests/ui/const-generics/issues/issue-71611.rs index c917f66818bad..9293009248218 100644 --- a/tests/ui/const-generics/issues/issue-71611.rs +++ b/tests/ui/const-generics/issues/issue-71611.rs @@ -3,8 +3,7 @@ #![cfg_attr(full, allow(incomplete_features))] fn func(outer: A) { - //[min]~^ ERROR: using function pointers as const generic parameters is forbidden - //~^^ ERROR: the type of const parameters must not depend on other generic parameters + //~^ ERROR: the type of const parameters must not depend on other generic parameters F(outer); } diff --git a/tests/ui/consts/const-err4.rs b/tests/ui/consts/const-err-enum-discriminant.rs similarity index 91% rename from tests/ui/consts/const-err4.rs rename to tests/ui/consts/const-err-enum-discriminant.rs index 107dc3f8234f3..ebb3e551ba814 100644 --- a/tests/ui/consts/const-err4.rs +++ b/tests/ui/consts/const-err-enum-discriminant.rs @@ -1,4 +1,3 @@ -// stderr-per-bitwidth #[derive(Copy, Clone)] union Foo { a: isize, diff --git a/tests/ui/consts/const-err4.32bit.stderr b/tests/ui/consts/const-err-enum-discriminant.stderr similarity index 87% rename from tests/ui/consts/const-err4.32bit.stderr rename to tests/ui/consts/const-err-enum-discriminant.stderr index 582a848ca603f..7cf34595dc972 100644 --- a/tests/ui/consts/const-err4.32bit.stderr +++ b/tests/ui/consts/const-err-enum-discriminant.stderr @@ -1,5 +1,5 @@ error[E0080]: evaluation of constant value failed - --> $DIR/const-err4.rs:9:21 + --> $DIR/const-err-enum-discriminant.rs:8:21 | LL | Boo = [unsafe { Foo { b: () }.a }; 4][3], | ^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory diff --git a/tests/ui/consts/const-err4.64bit.stderr b/tests/ui/consts/const-err4.64bit.stderr deleted file mode 100644 index 582a848ca603f..0000000000000 --- a/tests/ui/consts/const-err4.64bit.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0080]: evaluation of constant value failed - --> $DIR/const-err4.rs:9:21 - | -LL | Boo = [unsafe { Foo { b: () }.a }; 4][3], - | ^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/const-eval-query-stack.stderr b/tests/ui/consts/const-eval/const-eval-query-stack.stderr index 01fb8153cf384..c748af608d1e6 100644 --- a/tests/ui/consts/const-eval/const-eval-query-stack.stderr +++ b/tests/ui/consts/const-eval/const-eval-query-stack.stderr @@ -1,4 +1,4 @@ -error[E0080]: evaluation of constant value failed +error: internal compiler error[E0080]: evaluation of constant value failed --> $DIR/const-eval-query-stack.rs:16:16 | LL | const X: i32 = 1 / 0; diff --git a/tests/ui/delegation/bad-resolve.rs b/tests/ui/delegation/bad-resolve.rs new file mode 100644 index 0000000000000..df456f94507be --- /dev/null +++ b/tests/ui/delegation/bad-resolve.rs @@ -0,0 +1,47 @@ +#![feature(fn_delegation)] +//~^ WARN the feature `fn_delegation` is incomplete + +trait Trait { + const C: u32 = 0; + type Type; + fn bar() {} + fn foo(&self, x: i32) -> i32 { x } +} + +struct F; +impl Trait for F { + type Type = i32; +} + +impl F { + fn foo(&self, x: i32) -> i32 { x } +} + +struct S(F); + +impl Trait for S { +//~^ ERROR not all trait items implemented, missing: `Type` + reuse ::C; + //~^ ERROR item `C` is an associated method, which doesn't match its trait `Trait` + //~| ERROR expected function, found associated constant `Trait::C` + reuse ::Type; + //~^ ERROR item `Type` is an associated method, which doesn't match its trait `Trait` + //~| ERROR expected method or associated constant, found associated type `Trait::Type` + reuse ::baz; + //~^ ERROR method `baz` is not a member of trait `Trait` + //~| ERROR cannot find method or associated constant `baz` in trait `Trait` + reuse ::bar; + + reuse foo { &self.0 } + //~^ ERROR cannot find function `foo` in this scope + reuse F::foo { &self.0 } + //~^ ERROR cannot find function `foo` in `F` + //~| ERROR duplicate definitions with name `foo` +} + +impl S { + reuse F::foo { &self.0 } + //~^ ERROR cannot find function `foo` in `F` +} + +fn main() {} diff --git a/tests/ui/delegation/bad-resolve.stderr b/tests/ui/delegation/bad-resolve.stderr new file mode 100644 index 0000000000000..d520663731002 --- /dev/null +++ b/tests/ui/delegation/bad-resolve.stderr @@ -0,0 +1,102 @@ +error[E0324]: item `C` is an associated method, which doesn't match its trait `Trait` + --> $DIR/bad-resolve.rs:24:5 + | +LL | const C: u32 = 0; + | ----------------- item in trait +... +LL | reuse ::C; + | ^^^^^^^^^^^^^^^^^^^^^^ does not match trait + +error[E0324]: item `Type` is an associated method, which doesn't match its trait `Trait` + --> $DIR/bad-resolve.rs:27:5 + | +LL | type Type; + | ---------- item in trait +... +LL | reuse ::Type; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ does not match trait + +error[E0407]: method `baz` is not a member of trait `Trait` + --> $DIR/bad-resolve.rs:30:5 + | +LL | reuse ::baz; + | ^^^^^^^^^^^^^^^^^^^^---^ + | | | + | | help: there is an associated function with a similar name: `bar` + | not a member of trait `Trait` + +error[E0201]: duplicate definitions with name `foo`: + --> $DIR/bad-resolve.rs:37:5 + | +LL | fn foo(&self, x: i32) -> i32 { x } + | ---------------------------------- item in trait +... +LL | reuse foo { &self.0 } + | --------------------- previous definition here +LL | +LL | reuse F::foo { &self.0 } + | ^^^^^^^^^^^^^^^^^^^^^^^^ duplicate definition + +error[E0423]: expected function, found associated constant `Trait::C` + --> $DIR/bad-resolve.rs:24:11 + | +LL | reuse ::C; + | ^^^^^^^^^^^^^^^ not a function + +error[E0575]: expected method or associated constant, found associated type `Trait::Type` + --> $DIR/bad-resolve.rs:27:11 + | +LL | reuse ::Type; + | ^^^^^^^^^^^^^^^^^^ + | + = note: can't use a type alias as a constructor + +error[E0576]: cannot find method or associated constant `baz` in trait `Trait` + --> $DIR/bad-resolve.rs:30:25 + | +LL | fn bar() {} + | -------- similarly named associated function `bar` defined here +... +LL | reuse ::baz; + | ^^^ help: an associated function with a similar name exists: `bar` + +error[E0425]: cannot find function `foo` in this scope + --> $DIR/bad-resolve.rs:35:11 + | +LL | reuse foo { &self.0 } + | ^^^ not found in this scope + +error[E0425]: cannot find function `foo` in `F` + --> $DIR/bad-resolve.rs:37:14 + | +LL | reuse F::foo { &self.0 } + | ^^^ not found in `F` + +error[E0425]: cannot find function `foo` in `F` + --> $DIR/bad-resolve.rs:43:14 + | +LL | reuse F::foo { &self.0 } + | ^^^ not found in `F` + +warning: the feature `fn_delegation` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/bad-resolve.rs:1:12 + | +LL | #![feature(fn_delegation)] + | ^^^^^^^^^^^^^ + | + = note: see issue #118212 for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0046]: not all trait items implemented, missing: `Type` + --> $DIR/bad-resolve.rs:22:1 + | +LL | type Type; + | --------- `Type` from trait +... +LL | impl Trait for S { + | ^^^^^^^^^^^^^^^^ missing `Type` in implementation + +error: aborting due to 11 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0046, E0201, E0324, E0407, E0423, E0425, E0575, E0576. +For more information about an error, try `rustc --explain E0046`. diff --git a/tests/ui/delegation/explicit-paths-in-traits-pass.rs b/tests/ui/delegation/explicit-paths-in-traits-pass.rs new file mode 100644 index 0000000000000..5c41c2ff49c8d --- /dev/null +++ b/tests/ui/delegation/explicit-paths-in-traits-pass.rs @@ -0,0 +1,27 @@ +// run-pass + +#![feature(fn_delegation)] +//~^ WARN the feature `fn_delegation` is incomplete + +trait ToReuse { + fn foo(&self, x: i32) -> i32 { x } + fn foo1(x: i32) -> i32 { x } +} + +fn foo2() -> i32 { 42 } + +trait Trait: ToReuse { + reuse ToReuse::foo; + reuse ::foo1; + reuse foo2; +} + +struct S; +impl ToReuse for S {} +impl Trait for S {} + +fn main() { + assert_eq!(::foo(&S, 1), 1); + assert_eq!(::foo1(1), 1); + assert_eq!(::foo2(), 42); +} diff --git a/tests/ui/delegation/explicit-paths-in-traits-pass.stderr b/tests/ui/delegation/explicit-paths-in-traits-pass.stderr new file mode 100644 index 0000000000000..8a320b44e63db --- /dev/null +++ b/tests/ui/delegation/explicit-paths-in-traits-pass.stderr @@ -0,0 +1,11 @@ +warning: the feature `fn_delegation` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/explicit-paths-in-traits-pass.rs:3:12 + | +LL | #![feature(fn_delegation)] + | ^^^^^^^^^^^^^ + | + = note: see issue #118212 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/delegation/explicit-paths-pass.rs b/tests/ui/delegation/explicit-paths-pass.rs new file mode 100644 index 0000000000000..331e06d9a8879 --- /dev/null +++ b/tests/ui/delegation/explicit-paths-pass.rs @@ -0,0 +1,64 @@ +// run-pass + +#![feature(fn_delegation)] +//~^ WARN the feature `fn_delegation` is incomplete + +trait Trait { + fn bar(&self, x: i32) -> i32 { x } + fn description(&self) -> &str { + "hello world!" + } + fn static_method(x: i32) -> i32 { x } + fn static_method2(x: i32, y: i32) -> i32 { x + y } + fn baz<'a>(&self, x: &'a i32) -> &'a i32 { x } +} + +struct F; +impl Trait for F {} + +mod to_reuse { + pub fn foo(x: i32) -> i32 { x + 1 } + pub fn zero_args() -> i32 { 15 } +} + +reuse to_reuse::zero_args { self } + +struct S(F); +impl Trait for S { + reuse Trait::bar { &self.0 } + reuse Trait::description { &self.0 } + reuse ::static_method; + reuse ::static_method2 { S::static_method(self) } + reuse Trait::baz { &self.0 } +} + +impl S { + reuse Trait::baz { &self.0 } + reuse ::static_method { to_reuse::foo(self) } +} + +impl std::fmt::Display for S { + reuse ::fmt { self.description() } +} + +fn main() { + let s = S(F); + assert_eq!(42, s.bar(42)); + assert_eq!("hello world!", format!("{s}")); + assert_eq!(43, S::static_method(42)); + assert_eq!(42, ::static_method(42)); + assert_eq!(21, S::static_method2(10, 10)); + + reuse ::static_method; + reuse ::static_method2 { static_method(self) } + #[inline] + reuse to_reuse::foo; + assert_eq!(42, static_method(42)); + assert_eq!(21, static_method2(10, 10)); + assert_eq!(43, foo(42)); + assert_eq!(15, zero_args()); + + let x: i32 = 15; + assert_eq!(&x, ::baz(&s, &x)); + assert_eq!(&x, S::baz(&s, &x)); +} diff --git a/tests/ui/delegation/explicit-paths-pass.stderr b/tests/ui/delegation/explicit-paths-pass.stderr new file mode 100644 index 0000000000000..6d25fb4a5a57d --- /dev/null +++ b/tests/ui/delegation/explicit-paths-pass.stderr @@ -0,0 +1,11 @@ +warning: the feature `fn_delegation` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/explicit-paths-pass.rs:3:12 + | +LL | #![feature(fn_delegation)] + | ^^^^^^^^^^^^^ + | + = note: see issue #118212 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/delegation/explicit-paths-signature-pass.rs b/tests/ui/delegation/explicit-paths-signature-pass.rs new file mode 100644 index 0000000000000..826107130eb0e --- /dev/null +++ b/tests/ui/delegation/explicit-paths-signature-pass.rs @@ -0,0 +1,39 @@ +// run-pass + +#![feature(fn_delegation)] +//~^ WARN the feature `fn_delegation` is incomplete + +mod to_reuse { + use crate::S; + + pub fn foo<'a>(#[cfg(FALSE)] a: u8, _b: &'a S) -> u32 { + 1 + } +} + +reuse to_reuse::foo; + +trait Trait { + fn foo(&self) -> u32 { 0 } + fn bar(self: Box) -> u32 { 2 } + fn baz(a: (i32, i32)) -> i32 { a.0 + a.1 } +} + +struct F; +impl Trait for F {} + +struct S(F); + +impl Trait for S { + reuse to_reuse::foo { self } + reuse Trait::bar { Box::new(self.0) } + reuse ::baz; +} + +fn main() { + let s = S(F); + assert_eq!(1, foo(&s)); + assert_eq!(1, s.foo()); + assert_eq!(2, Box::new(s).bar()); + assert_eq!(4, S::baz((2, 2))); +} diff --git a/tests/ui/delegation/explicit-paths-signature-pass.stderr b/tests/ui/delegation/explicit-paths-signature-pass.stderr new file mode 100644 index 0000000000000..6c81a2ea0af73 --- /dev/null +++ b/tests/ui/delegation/explicit-paths-signature-pass.stderr @@ -0,0 +1,11 @@ +warning: the feature `fn_delegation` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/explicit-paths-signature-pass.rs:3:12 + | +LL | #![feature(fn_delegation)] + | ^^^^^^^^^^^^^ + | + = note: see issue #118212 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/delegation/explicit-paths.rs b/tests/ui/delegation/explicit-paths.rs new file mode 100644 index 0000000000000..1feaaa73f79e8 --- /dev/null +++ b/tests/ui/delegation/explicit-paths.rs @@ -0,0 +1,25 @@ +#![feature(fn_delegation)] +//~^ WARN the feature `fn_delegation` is incomplete + +trait Trait { + fn bar(&self) -> i32 { 42 } +} + +struct F; +impl Trait for F {} + +struct S(F); + +impl Trait for S { + reuse ::bar; + //~^ ERROR mismatched types +} + +struct S2(F); + +impl Trait for S2 { + reuse ::bar { &self.0 } + //~^ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/delegation/explicit-paths.stderr b/tests/ui/delegation/explicit-paths.stderr new file mode 100644 index 0000000000000..2994b2390dedf --- /dev/null +++ b/tests/ui/delegation/explicit-paths.stderr @@ -0,0 +1,38 @@ +warning: the feature `fn_delegation` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/explicit-paths.rs:1:12 + | +LL | #![feature(fn_delegation)] + | ^^^^^^^^^^^^^ + | + = note: see issue #118212 for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0308]: mismatched types + --> $DIR/explicit-paths.rs:14:25 + | +LL | reuse ::bar; + | --------------^^^ + | | | + | | expected `&F`, found `&S` + | arguments to this function are incorrect + | + = note: expected reference `&F` + found reference `&S` +note: method defined here + --> $DIR/explicit-paths.rs:5:8 + | +LL | fn bar(&self) -> i32 { 42 } + | ^^^ ----- + +error[E0308]: mismatched types + --> $DIR/explicit-paths.rs:21:32 + | +LL | reuse ::bar { &self.0 } + | ^^^^^^^ expected `&S2`, found `&F` + | + = note: expected reference `&S2` + found reference `&F` + +error: aborting due to 2 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/delegation/not-supported.rs b/tests/ui/delegation/not-supported.rs new file mode 100644 index 0000000000000..23081b1e1fc8b --- /dev/null +++ b/tests/ui/delegation/not-supported.rs @@ -0,0 +1,111 @@ +#![feature(c_variadic)] +#![feature(fn_delegation)] +//~^ WARN the feature `fn_delegation` is incomplete + +mod generics { + trait GenericTrait { + fn bar(&self, x: T) -> T { x } + fn bar1() {} + } + trait Trait { + fn foo(&self, x: i32) -> i32 { x } + fn foo1<'a>(&self, x: &'a i32) -> &'a i32 { x } + fn foo2(&self, x: T) -> T { x } + fn foo3<'a: 'a>(_: &'a u32) {} + + reuse GenericTrait::bar; + //~^ delegation with early bound generics is not supported yet + reuse GenericTrait::bar1; + //~^ delegation with early bound generics is not supported yet + } + + struct F; + impl Trait for F {} + impl GenericTrait for F {} + + struct S(F); + + impl GenericTrait for S { + reuse >::bar { &self.0 } + //~^ ERROR delegation with early bound generics is not supported yet + reuse GenericTrait::::bar1; + //~^ ERROR delegation with early bound generics is not supported yet + } + + impl GenericTrait<()> for () { + reuse GenericTrait::bar { &F } + //~^ ERROR delegation with early bound generics is not supported yet + reuse GenericTrait::bar1; + //~^ ERROR delegation with early bound generics is not supported yet + } + + impl Trait for &S { + reuse Trait::foo; + //~^ ERROR delegation with early bound generics is not supported yet + } + + impl Trait for S { + reuse Trait::foo1 { &self.0 } + reuse Trait::foo2 { &self.0 } + //~^ ERROR delegation with early bound generics is not supported yet + //~| ERROR method `foo2` has 0 type parameters but its trait declaration has 1 type parameter + reuse ::foo3; + //~^ ERROR delegation with early bound generics is not supported yet + //~| ERROR lifetime parameters or bounds on method `foo3` do not match the trait declaration + } + + struct GenericS(T); + impl Trait for GenericS { + reuse Trait::foo { &self.0 } + //~^ ERROR delegation with early bound generics is not supported yet + } +} + +mod opaque { + trait Trait {} + impl Trait for () {} + + mod to_reuse { + use super::Trait; + + pub fn opaque_arg(_: impl Trait) -> i32 { 0 } + pub fn opaque_ret() -> impl Trait { unimplemented!() } + } + reuse to_reuse::opaque_arg; + //~^ ERROR delegation with early bound generics is not supported yet + reuse to_reuse::opaque_ret; + //~^ ERROR delegation to a function with opaque type is not supported yet +} + +mod fn_header { + mod to_reuse { + pub unsafe fn unsafe_fn() {} + pub extern "C" fn extern_fn() {} + pub unsafe extern "C" fn variadic_fn(n: usize, mut args: ...) {} + pub const fn const_fn() {} + } + + reuse to_reuse::unsafe_fn; + //~^ ERROR delegation to unsafe functions is not supported yet + reuse to_reuse::extern_fn; + //~^ ERROR delegation to non Rust ABI functions is not supported yet + reuse to_reuse::variadic_fn; + //~^ ERROR delegation to variadic functions is not supported yet + reuse to_reuse::const_fn; + //~^ ERROR delegation to const functions is not supported yet +} + +mod recursive { + mod to_reuse1 { + pub mod to_reuse2 { + pub fn foo() {} + } + + pub reuse to_reuse2::foo; + } + + reuse to_reuse1::foo; + //~^ ERROR recursive delegation is not supported yet +} + +fn main() {} diff --git a/tests/ui/delegation/not-supported.stderr b/tests/ui/delegation/not-supported.stderr new file mode 100644 index 0000000000000..f235767d50afc --- /dev/null +++ b/tests/ui/delegation/not-supported.stderr @@ -0,0 +1,184 @@ +warning: the feature `fn_delegation` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/not-supported.rs:2:12 + | +LL | #![feature(fn_delegation)] + | ^^^^^^^^^^^^^ + | + = note: see issue #118212 for more information + = note: `#[warn(incomplete_features)]` on by default + +error: delegation with early bound generics is not supported yet + --> $DIR/not-supported.rs:16:29 + | +LL | fn bar(&self, x: T) -> T { x } + | ------------------------ callee defined here +... +LL | reuse GenericTrait::bar; + | ^^^ + +error: delegation with early bound generics is not supported yet + --> $DIR/not-supported.rs:18:29 + | +LL | fn bar1() {} + | --------- callee defined here +... +LL | reuse GenericTrait::bar1; + | ^^^^ + +error: delegation with early bound generics is not supported yet + --> $DIR/not-supported.rs:29:39 + | +LL | fn bar(&self, x: T) -> T { x } + | ------------------------ callee defined here +... +LL | reuse >::bar { &self.0 } + | ^^^ + +error: delegation with early bound generics is not supported yet + --> $DIR/not-supported.rs:31:34 + | +LL | fn bar1() {} + | --------- callee defined here +... +LL | reuse GenericTrait::::bar1; + | ^^^^ + +error: delegation with early bound generics is not supported yet + --> $DIR/not-supported.rs:36:29 + | +LL | fn bar(&self, x: T) -> T { x } + | ------------------------ callee defined here +... +LL | reuse GenericTrait::bar { &F } + | ^^^ + +error: delegation with early bound generics is not supported yet + --> $DIR/not-supported.rs:38:29 + | +LL | fn bar1() {} + | --------- callee defined here +... +LL | reuse GenericTrait::bar1; + | ^^^^ + +error: delegation with early bound generics is not supported yet + --> $DIR/not-supported.rs:43:22 + | +LL | fn foo(&self, x: i32) -> i32 { x } + | ---------------------------- callee defined here +... +LL | reuse Trait::foo; + | ^^^ + +error: delegation with early bound generics is not supported yet + --> $DIR/not-supported.rs:49:22 + | +LL | fn foo2(&self, x: T) -> T { x } + | ---------------------------- callee defined here +... +LL | reuse Trait::foo2 { &self.0 } + | ^^^^ + +error: delegation with early bound generics is not supported yet + --> $DIR/not-supported.rs:52:29 + | +LL | fn foo3<'a: 'a>(_: &'a u32) {} + | --------------------------- callee defined here +... +LL | reuse ::foo3; + | ^^^^ + +error: delegation with early bound generics is not supported yet + --> $DIR/not-supported.rs:59:22 + | +LL | fn foo(&self, x: i32) -> i32 { x } + | ---------------------------- callee defined here +... +LL | reuse Trait::foo { &self.0 } + | ^^^ + +error: delegation with early bound generics is not supported yet + --> $DIR/not-supported.rs:74:21 + | +LL | pub fn opaque_arg(_: impl Trait) -> i32 { 0 } + | --------------------------------------- callee defined here +... +LL | reuse to_reuse::opaque_arg; + | ^^^^^^^^^^ + +error: delegation to a function with opaque type is not supported yet + --> $DIR/not-supported.rs:76:21 + | +LL | pub fn opaque_ret() -> impl Trait { unimplemented!() } + | --------------------------------- callee defined here +... +LL | reuse to_reuse::opaque_ret; + | ^^^^^^^^^^ + +error: delegation to unsafe functions is not supported yet + --> $DIR/not-supported.rs:88:21 + | +LL | pub unsafe fn unsafe_fn() {} + | ------------------------- callee defined here +... +LL | reuse to_reuse::unsafe_fn; + | ^^^^^^^^^ + +error: delegation to non Rust ABI functions is not supported yet + --> $DIR/not-supported.rs:90:21 + | +LL | pub extern "C" fn extern_fn() {} + | ----------------------------- callee defined here +... +LL | reuse to_reuse::extern_fn; + | ^^^^^^^^^ + +error: delegation to variadic functions is not supported yet + --> $DIR/not-supported.rs:92:21 + | +LL | pub unsafe extern "C" fn variadic_fn(n: usize, mut args: ...) {} + | ------------------------------------------------------------- callee defined here +... +LL | reuse to_reuse::variadic_fn; + | ^^^^^^^^^^^ + +error: delegation to const functions is not supported yet + --> $DIR/not-supported.rs:94:21 + | +LL | pub const fn const_fn() {} + | ----------------------- callee defined here +... +LL | reuse to_reuse::const_fn; + | ^^^^^^^^ + +error: recursive delegation is not supported yet + --> $DIR/not-supported.rs:107:22 + | +LL | pub reuse to_reuse2::foo; + | --- callee defined here +... +LL | reuse to_reuse1::foo; + | ^^^ + +error[E0049]: method `foo2` has 0 type parameters but its trait declaration has 1 type parameter + --> $DIR/not-supported.rs:49:22 + | +LL | fn foo2(&self, x: T) -> T { x } + | - expected 1 type parameter +... +LL | reuse Trait::foo2 { &self.0 } + | ^^^^ found 0 type parameters + +error[E0195]: lifetime parameters or bounds on method `foo3` do not match the trait declaration + --> $DIR/not-supported.rs:52:29 + | +LL | fn foo3<'a: 'a>(_: &'a u32) {} + | -------- lifetimes in impl do not match this method in trait +... +LL | reuse ::foo3; + | ^^^^ lifetimes do not match method in trait + +error: aborting due to 19 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0049, E0195. +For more information about an error, try `rustc --explain E0049`. diff --git a/tests/ui/delegation/parse.rs b/tests/ui/delegation/parse.rs new file mode 100644 index 0000000000000..791cc1630ff7d --- /dev/null +++ b/tests/ui/delegation/parse.rs @@ -0,0 +1,42 @@ +// check-pass + +#![feature(decl_macro)] +#![feature(fn_delegation)] +//~^ WARN the feature `fn_delegation` is incomplete + +macro_rules! reuse { {} => {} } + +mod reuse { + pub fn to_unsafe(x: i32) -> i32 { x + 1 } + pub fn to_pub() {} + pub fn to_pub2() {} + + mod inner { + #[allow(non_camel_case_types)] + struct reuse { + a: i32, + b: i32, + c: i32, + } + + impl reuse { + reuse!(); + } + + fn baz() { + let (a, b, c) = (0, 0, 0); + reuse {a, b, c}; + } + } + + pub macro my_macro() {} +} + +reuse!(); +reuse::my_macro!(); + +#[inline] +pub reuse reuse::to_pub; +pub reuse crate::reuse::to_pub2; + +fn main() {} diff --git a/tests/ui/delegation/parse.stderr b/tests/ui/delegation/parse.stderr new file mode 100644 index 0000000000000..1e420ceeec7f1 --- /dev/null +++ b/tests/ui/delegation/parse.stderr @@ -0,0 +1,11 @@ +warning: the feature `fn_delegation` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/parse.rs:4:12 + | +LL | #![feature(fn_delegation)] + | ^^^^^^^^^^^^^ + | + = note: see issue #118212 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/delegation/target-expr-pass.rs b/tests/ui/delegation/target-expr-pass.rs new file mode 100644 index 0000000000000..56068dfce01d7 --- /dev/null +++ b/tests/ui/delegation/target-expr-pass.rs @@ -0,0 +1,37 @@ +// run-pass + +#![feature(fn_delegation)] +//~^ WARN the feature `fn_delegation` is incomplete + +mod to_reuse { + pub fn foo(x: i32) -> i32 { x } + pub mod inner {} +} + +reuse to_reuse::foo {{ + use self::to_reuse::foo; + let x = foo(12); + x + self +}} + +trait Trait { + fn bar(&self, x: i32) -> i32 { x } +} + +struct F; +impl Trait for F {} + +struct S(F); +impl Trait for S { + reuse ::bar { + #[allow(unused_imports)] + use self::to_reuse::{foo, inner::self}; + let x = foo(12); + assert_eq!(x, 12); + &self.0 + } +} + +fn main() { + assert_eq!(foo(12), 24); +} diff --git a/tests/ui/delegation/target-expr-pass.stderr b/tests/ui/delegation/target-expr-pass.stderr new file mode 100644 index 0000000000000..ea594f8a26a5b --- /dev/null +++ b/tests/ui/delegation/target-expr-pass.stderr @@ -0,0 +1,11 @@ +warning: the feature `fn_delegation` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/target-expr-pass.rs:3:12 + | +LL | #![feature(fn_delegation)] + | ^^^^^^^^^^^^^ + | + = note: see issue #118212 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/derives/issue-97343.rs b/tests/ui/derives/issue-97343.rs index 91f0aa376e9ae..6f0e4d55aeb04 100644 --- a/tests/ui/derives/issue-97343.rs +++ b/tests/ui/derives/issue-97343.rs @@ -2,7 +2,6 @@ use std::fmt::Debug; #[derive(Debug)] pub struct Irrelevant { //~ ERROR type arguments are not allowed on type parameter - //~^ ERROR `Irrelevant` must be used irrelevant: Irrelevant, } diff --git a/tests/ui/derives/issue-97343.stderr b/tests/ui/derives/issue-97343.stderr index 45612ae6f4747..efb2fb70f5a51 100644 --- a/tests/ui/derives/issue-97343.stderr +++ b/tests/ui/derives/issue-97343.stderr @@ -16,16 +16,6 @@ LL | pub struct Irrelevant { | ^^^^^^^^^^ = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0210]: type parameter `Irrelevant` must be used as the type parameter for some local type (e.g., `MyStruct`) - --> $DIR/issue-97343.rs:4:23 - | -LL | pub struct Irrelevant { - | ^^^^^^^^^^ type parameter `Irrelevant` must be used as the type parameter for some local type - | - = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local - = note: only traits defined in the current crate can be implemented for a type parameter - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0109, E0210. -For more information about an error, try `rustc --explain E0109`. +For more information about this error, try `rustc --explain E0109`. diff --git a/tests/ui/error-codes/E0227.rs b/tests/ui/error-codes/E0227.rs index 4dd4da55fa323..bab6d8af476e3 100644 --- a/tests/ui/error-codes/E0227.rs +++ b/tests/ui/error-codes/E0227.rs @@ -6,8 +6,6 @@ trait FooBar<'foo, 'bar>: Foo<'foo> + Bar<'bar> {} struct Baz<'foo, 'bar> { baz: dyn FooBar<'foo, 'bar>, //~^ ERROR ambiguous lifetime bound, explicit lifetime bound required - //~| ERROR lifetime bound not satisfied } -fn main() { -} +fn main() {} diff --git a/tests/ui/error-codes/E0227.stderr b/tests/ui/error-codes/E0227.stderr index 6338034a022a3..c77a2e98af70e 100644 --- a/tests/ui/error-codes/E0227.stderr +++ b/tests/ui/error-codes/E0227.stderr @@ -4,24 +4,6 @@ error[E0227]: ambiguous lifetime bound, explicit lifetime bound required LL | baz: dyn FooBar<'foo, 'bar>, | ^^^^^^^^^^^^^^^^^^^^^^ -error[E0478]: lifetime bound not satisfied - --> $DIR/E0227.rs:7:10 - | -LL | baz: dyn FooBar<'foo, 'bar>, - | ^^^^^^^^^^^^^^^^^^^^^^ - | -note: lifetime parameter instantiated with the lifetime `'bar` as defined here - --> $DIR/E0227.rs:6:18 - | -LL | struct Baz<'foo, 'bar> { - | ^^^^ -note: but lifetime parameter must outlive the lifetime `'foo` as defined here - --> $DIR/E0227.rs:6:12 - | -LL | struct Baz<'foo, 'bar> { - | ^^^^ - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0227, E0478. -For more information about an error, try `rustc --explain E0227`. +For more information about this error, try `rustc --explain E0227`. diff --git a/tests/ui/feature-gates/feature-gate-fn_delegation.rs b/tests/ui/feature-gates/feature-gate-fn_delegation.rs index 6ac3671209033..5352b2d8cadb4 100644 --- a/tests/ui/feature-gates/feature-gate-fn_delegation.rs +++ b/tests/ui/feature-gates/feature-gate-fn_delegation.rs @@ -1,3 +1,8 @@ -todo!(); //~ ERROR +mod to_reuse { + pub fn foo() {} +} + +reuse to_reuse::foo; +//~^ ERROR functions delegation is not yet fully implemented fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-fn_delegation.stderr b/tests/ui/feature-gates/feature-gate-fn_delegation.stderr index 14d85c5263e0d..9b62e4ecff44f 100644 --- a/tests/ui/feature-gates/feature-gate-fn_delegation.stderr +++ b/tests/ui/feature-gates/feature-gate-fn_delegation.stderr @@ -1,13 +1,12 @@ -error: expected one of `!` or `::`, found `(` - --> $DIR/feature-gate-fn_delegation.rs:1:1 +error[E0658]: functions delegation is not yet fully implemented + --> $DIR/feature-gate-fn_delegation.rs:5:1 | -LL | todo!(); - | ^^^^^^^ - | | - | expected one of `!` or `::` - | in this macro invocation +LL | reuse to_reuse::foo; + | ^^^^^^^^^^^^^^^^^^^^ | - = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: see issue #118212 for more information + = help: add `#![feature(fn_delegation)]` to the crate attributes to enable error: aborting due to 1 previous error +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/generic-associated-types/issue-71176.rs b/tests/ui/generic-associated-types/issue-71176.rs index e58b6f6091e75..f0e162d825f9d 100644 --- a/tests/ui/generic-associated-types/issue-71176.rs +++ b/tests/ui/generic-associated-types/issue-71176.rs @@ -9,9 +9,6 @@ impl Provider for () { struct Holder { inner: Box>, //~^ ERROR: missing generics for associated type - //~| ERROR: missing generics for associated type - //~| ERROR: missing generics for associated type - //~| ERROR: the trait `Provider` cannot be made into an object } fn main() { diff --git a/tests/ui/generic-associated-types/issue-71176.stderr b/tests/ui/generic-associated-types/issue-71176.stderr index a1913bb618bc0..ed837f3475338 100644 --- a/tests/ui/generic-associated-types/issue-71176.stderr +++ b/tests/ui/generic-associated-types/issue-71176.stderr @@ -14,57 +14,6 @@ help: add missing lifetime argument LL | inner: Box = B>>, | ++++ -error[E0107]: missing generics for associated type `Provider::A` - --> $DIR/issue-71176.rs:10:27 - | -LL | inner: Box>, - | ^ expected 1 lifetime argument - | -note: associated type defined here, with 1 lifetime parameter: `'a` - --> $DIR/issue-71176.rs:2:10 - | -LL | type A<'a>; - | ^ -- - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: add missing lifetime argument - | -LL | inner: Box = B>>, - | ++++ - -error[E0107]: missing generics for associated type `Provider::A` - --> $DIR/issue-71176.rs:10:27 - | -LL | inner: Box>, - | ^ expected 1 lifetime argument - | -note: associated type defined here, with 1 lifetime parameter: `'a` - --> $DIR/issue-71176.rs:2:10 - | -LL | type A<'a>; - | ^ -- - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: add missing lifetime argument - | -LL | inner: Box = B>>, - | ++++ - -error[E0038]: the trait `Provider` cannot be made into an object - --> $DIR/issue-71176.rs:10:14 - | -LL | inner: Box>, - | ^^^^^^^^^^^^^^^^^^^ `Provider` cannot be made into an object - | -note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/issue-71176.rs:2:10 - | -LL | trait Provider { - | -------- this trait cannot be made into an object... -LL | type A<'a>; - | ^ ...because it contains the generic associated type `A` - = help: consider moving `A` to another trait - = help: only type `()` implements the trait, consider using it directly instead - -error: aborting due to 4 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0038, E0107. -For more information about an error, try `rustc --explain E0038`. +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/hygiene/panic-location.run.stderr b/tests/ui/hygiene/panic-location.run.stderr index 5c552411da7f3..5824ef31211be 100644 --- a/tests/ui/hygiene/panic-location.run.stderr +++ b/tests/ui/hygiene/panic-location.run.stderr @@ -1,3 +1,3 @@ -thread 'main' panicked at library/alloc/src/raw_vec.rs:571:5: +thread 'main' panicked at library/alloc/src/raw_vec.rs:570:5: capacity overflow note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace diff --git a/tests/ui/impl-trait/issues/issue-86800.stderr b/tests/ui/impl-trait/issues/issue-86800.stderr index 07ba8eb021b31..7af4846a9593f 100644 --- a/tests/ui/impl-trait/issues/issue-86800.stderr +++ b/tests/ui/impl-trait/issues/issue-86800.stderr @@ -4,7 +4,7 @@ error: unconstrained opaque type LL | type TransactionFuture<'__, O> = impl '__ + Future>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -error[E0792]: expected generic lifetime parameter, found `'_` +error: internal compiler error[E0792]: expected generic lifetime parameter, found `'_` --> $DIR/issue-86800.rs:39:5 | LL | type TransactionFuture<'__, O> = impl '__ + Future>; diff --git a/tests/ui/issues/issue-3214.rs b/tests/ui/issues/issue-3214.rs index 03d8d6ba24651..b2c27f5be957c 100644 --- a/tests/ui/issues/issue-3214.rs +++ b/tests/ui/issues/issue-3214.rs @@ -5,7 +5,6 @@ fn foo() { impl Drop for Foo { //~^ ERROR struct takes 0 generic arguments but 1 generic argument - //~| ERROR `T` is not constrained fn drop(&mut self) {} } } diff --git a/tests/ui/issues/issue-3214.stderr b/tests/ui/issues/issue-3214.stderr index 26ac6d39f6014..5b57c1baf90ba 100644 --- a/tests/ui/issues/issue-3214.stderr +++ b/tests/ui/issues/issue-3214.stderr @@ -22,13 +22,7 @@ note: struct defined here, with 0 generic parameters LL | struct Foo { | ^^^ -error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates - --> $DIR/issue-3214.rs:6:10 - | -LL | impl Drop for Foo { - | ^ unconstrained type parameter - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0107, E0207, E0401. +Some errors have detailed explanations: E0107, E0401. For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/layout/issue-84108.rs b/tests/ui/layout/issue-84108.rs index af21d1d6210b6..44d6ac8db72f0 100644 --- a/tests/ui/layout/issue-84108.rs +++ b/tests/ui/layout/issue-84108.rs @@ -8,8 +8,6 @@ static FOO: (dyn AsRef, u8) = ("hello", 42); const BAR: (&Path, [u8], usize) = ("hello", [], 42); //~^ ERROR cannot find type `Path` in this scope -//~| ERROR the size for values of type `[u8]` cannot be known at compilation time -//~| ERROR mismatched types static BAZ: ([u8], usize) = ([], 0); //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time diff --git a/tests/ui/layout/issue-84108.stderr b/tests/ui/layout/issue-84108.stderr index d6d7585103469..58bddb069fc7d 100644 --- a/tests/ui/layout/issue-84108.stderr +++ b/tests/ui/layout/issue-84108.stderr @@ -21,25 +21,7 @@ LL + use std::path::Path; | error[E0277]: the size for values of type `[u8]` cannot be known at compilation time - --> $DIR/issue-84108.rs:9:12 - | -LL | const BAR: (&Path, [u8], usize) = ("hello", [], 42); - | ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for `[u8]` - = note: only the last element of a tuple may have a dynamically sized type - -error[E0308]: mismatched types - --> $DIR/issue-84108.rs:9:45 - | -LL | const BAR: (&Path, [u8], usize) = ("hello", [], 42); - | ^^ expected `[u8]`, found `[_; 0]` - | - = note: expected slice `[u8]` - found array `[_; 0]` - -error[E0277]: the size for values of type `[u8]` cannot be known at compilation time - --> $DIR/issue-84108.rs:14:13 + --> $DIR/issue-84108.rs:12:13 | LL | static BAZ: ([u8], usize) = ([], 0); | ^^^^^^^^^^^^^ doesn't have a size known at compile-time @@ -48,7 +30,7 @@ LL | static BAZ: ([u8], usize) = ([], 0); = note: only the last element of a tuple may have a dynamically sized type error[E0308]: mismatched types - --> $DIR/issue-84108.rs:14:30 + --> $DIR/issue-84108.rs:12:30 | LL | static BAZ: ([u8], usize) = ([], 0); | ^^ expected `[u8]`, found `[_; 0]` @@ -56,7 +38,7 @@ LL | static BAZ: ([u8], usize) = ([], 0); = note: expected slice `[u8]` found array `[_; 0]` -error: aborting due to 6 previous errors +error: aborting due to 4 previous errors Some errors have detailed explanations: E0277, E0308, E0412. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/lifetimes/unusual-rib-combinations.rs b/tests/ui/lifetimes/unusual-rib-combinations.rs index 2f5ba98445bdc..a2461cff93265 100644 --- a/tests/ui/lifetimes/unusual-rib-combinations.rs +++ b/tests/ui/lifetimes/unusual-rib-combinations.rs @@ -28,6 +28,5 @@ fn d() {} trait Foo<'a> {} struct Bar Foo<'a>)>; //~^ ERROR the type of const parameters must not depend on other generic parameters -//~| ERROR `&dyn for<'a> Foo<'a>` is forbidden as the type of a const generic parameter fn main() {} diff --git a/tests/ui/lifetimes/unusual-rib-combinations.stderr b/tests/ui/lifetimes/unusual-rib-combinations.stderr index 92a2ef2f432f1..e3b70232ef86c 100644 --- a/tests/ui/lifetimes/unusual-rib-combinations.stderr +++ b/tests/ui/lifetimes/unusual-rib-combinations.stderr @@ -58,16 +58,7 @@ LL | fn d() {} = note: the only supported types are integers, `bool` and `char` = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types -error: `&dyn for<'a> Foo<'a>` is forbidden as the type of a const generic parameter - --> $DIR/unusual-rib-combinations.rs:29:21 - | -LL | struct Bar Foo<'a>)>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: the only supported types are integers, `bool` and `char` - = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types - -error: aborting due to 9 previous errors +error: aborting due to 8 previous errors Some errors have detailed explanations: E0106, E0214, E0308, E0770. For more information about an error, try `rustc --explain E0106`. diff --git a/tests/ui/panics/default-backtrace-ice.stderr b/tests/ui/panics/default-backtrace-ice.stderr index 4b00f13504758..9d27cb22ae942 100644 --- a/tests/ui/panics/default-backtrace-ice.stderr +++ b/tests/ui/panics/default-backtrace-ice.stderr @@ -1,4 +1,4 @@ -error[E0425]: cannot find value `missing_ident` in this scope +error: internal compiler error[E0425]: cannot find value `missing_ident` in this scope --> $DIR/default-backtrace-ice.rs:21:13 | LL | fn main() { missing_ident; } diff --git a/tests/ui/parser/issues/issue-103748-ICE-wrong-braces.rs b/tests/ui/parser/issues/issue-103748-ICE-wrong-braces.rs index 8012cb652bd88..f6aa39df27d8b 100644 --- a/tests/ui/parser/issues/issue-103748-ICE-wrong-braces.rs +++ b/tests/ui/parser/issues/issue-103748-ICE-wrong-braces.rs @@ -5,4 +5,3 @@ struct Apple((Apple, Option(Banana ? Citron))); //~| ERROR expected one of `)` or `,`, found `Citron` //~| ERROR cannot find type `Citron` in this scope [E0412] //~| ERROR parenthesized type parameters may only be used with a `Fn` trait [E0214] -//~| ERROR recursive type `Apple` has infinite size [E0072] diff --git a/tests/ui/parser/issues/issue-103748-ICE-wrong-braces.stderr b/tests/ui/parser/issues/issue-103748-ICE-wrong-braces.stderr index b0d8b03ae08c3..71d2d7b797582 100644 --- a/tests/ui/parser/issues/issue-103748-ICE-wrong-braces.stderr +++ b/tests/ui/parser/issues/issue-103748-ICE-wrong-braces.stderr @@ -34,18 +34,7 @@ help: use angle brackets instead LL | struct Apple((Apple, Option)); | ~ ~ -error[E0072]: recursive type `Apple` has infinite size - --> $DIR/issue-103748-ICE-wrong-braces.rs:3:1 - | -LL | struct Apple((Apple, Option(Banana ? Citron))); - | ^^^^^^^^^^^^ ----- recursive without indirection - | -help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle - | -LL | struct Apple((Box, Option(Banana ? Citron))); - | ++++ + - -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors -Some errors have detailed explanations: E0072, E0214, E0412. -For more information about an error, try `rustc --explain E0072`. +Some errors have detailed explanations: E0214, E0412. +For more information about an error, try `rustc --explain E0214`. diff --git a/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.rs b/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.rs index 4cbc36f4650b9..52ecbcc9e2cb3 100644 --- a/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.rs +++ b/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.rs @@ -39,7 +39,6 @@ impl> Struct {} trait YetAnotherTrait {} impl, U> YetAnotherTrait for Struct {} //~^ ERROR struct takes 1 generic argument but 2 generic arguments were supplied -//~| ERROR `U` is not constrained fn main() { diff --git a/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.stderr b/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.stderr index 3c2b726fccea4..e7ceb7372bfca 100644 --- a/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.stderr +++ b/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.stderr @@ -116,13 +116,7 @@ error[E0207]: the type parameter `S` is not constrained by the impl trait, self LL | impl Trait for () {} | ^ unconstrained type parameter -error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates - --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:40:35 - | -LL | impl, U> YetAnotherTrait for Struct {} - | ^ unconstrained type parameter - -error: aborting due to 10 previous errors +error: aborting due to 9 previous errors Some errors have detailed explanations: E0107, E0207. For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/treat-err-as-bug/err.stderr b/tests/ui/treat-err-as-bug/err.stderr index 3a56445a26b58..4c5d0e5ae7987 100644 --- a/tests/ui/treat-err-as-bug/err.stderr +++ b/tests/ui/treat-err-as-bug/err.stderr @@ -1,4 +1,4 @@ -error[E0080]: could not evaluate static initializer +error: internal compiler error[E0080]: could not evaluate static initializer --> $DIR/err.rs:11:21 | LL | pub static C: u32 = 0 - 1;