diff options
| author | bors <bors@rust-lang.org> | 2024-01-14 05:53:49 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2024-01-14 05:53:49 +0000 |
| commit | 0c8e1e6f444d28742aff75f8789df69007ca589a (patch) | |
| tree | 723640d4a742437fa21727738102037a96bcd605 /compiler | |
| parent | 12c0f090af379f2a6334cc35100cb6ee3f13f0ef (diff) | |
| parent | 6a234be984fc9df425a7e157c05f4b2739b18f55 (diff) | |
| download | rust-0c8e1e6f444d28742aff75f8789df69007ca589a.tar.gz rust-0c8e1e6f444d28742aff75f8789df69007ca589a.zip | |
Auto merge of #3267 - rust-lang:rustup-2024-01-14, r=saethlin
Automatic Rustup
Diffstat (limited to 'compiler')
90 files changed, 1210 insertions, 442 deletions
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index e1e4e5fc567..21077c312bd 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), @@ -3020,6 +3021,15 @@ pub struct Fn { } #[derive(Clone, Encodable, Decodable, Debug)] +pub struct Delegation { + /// Path resolution id. + pub id: NodeId, + pub qself: Option<P<QSelf>>, + pub path: Path, + pub body: Option<P<Block>>, +} + +#[derive(Clone, Encodable, Decodable, Debug)] pub struct StaticItem { pub ty: P<Ty>, pub mutability: Mutability, @@ -3104,6 +3114,11 @@ pub enum ItemKind { /// A macro definition. MacroDef(MacroDef), + + /// A delegation item (`reuse`). + /// + /// E.g. `reuse <Type as Trait>::name { target_expr_template }`. + Delegation(Box<Delegation>), } 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<TyAlias>), /// A macro expanding to associated items. MacCall(P<MacCall>), + /// An associated delegation item. + Delegation(Box<Delegation>), } 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<AssocItemKind> 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<ItemKind> 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 82f28143630..450555d0cb5 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<T: MutVisitor>(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<T: MutVisitor>( 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 45261ca48fc..3617df931e2 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/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index a5986f2bba5..3742cf9d881 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -48,7 +48,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ); if !is_stable && !self.tcx.features().asm_experimental_arch { feature_err( - &self.tcx.sess.parse_sess, + &self.tcx.sess, sym::asm_experimental_arch, sp, "inline assembly is not stable yet on this architecture", @@ -63,13 +63,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.dcx().emit_err(AttSyntaxOnlyX86 { span: sp }); } if asm.options.contains(InlineAsmOptions::MAY_UNWIND) && !self.tcx.features().asm_unwind { - feature_err( - &self.tcx.sess.parse_sess, - sym::asm_unwind, - sp, - "the `may_unwind` option is unstable", - ) - .emit(); + feature_err(&self.tcx.sess, sym::asm_unwind, sp, "the `may_unwind` option is unstable") + .emit(); } let mut clobber_abis = FxIndexMap::default(); @@ -183,7 +178,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { InlineAsmOperand::Const { anon_const } => { if !self.tcx.features().asm_const { feature_err( - &sess.parse_sess, + sess, sym::asm_const, *op_sp, "const operands for inline assembly are unstable", diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs new file mode 100644 index 00000000000..6ccf39b0cb1 --- /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 <Type as Trait>::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. `<Type as Trait>::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<DefId, ErrorGuaranteed> { + 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<hir::Param<'_>> = Vec::new(); + let mut args: Vec<hir::Expr<'hir>> = 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/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 69704de105c..e0b1a10c82e 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -1512,7 +1512,7 @@ impl<'hir> LoweringContext<'_, 'hir> { Some(hir::CoroutineKind::Coroutine(_)) => { if !self.tcx.features().coroutines { rustc_session::parse::feature_err( - &self.tcx.sess.parse_sess, + &self.tcx.sess, sym::coroutines, span, "yield syntax is experimental", @@ -1524,7 +1524,7 @@ impl<'hir> LoweringContext<'_, 'hir> { None => { if !self.tcx.features().coroutines { rustc_session::parse::feature_err( - &self.tcx.sess.parse_sess, + &self.tcx.sess, sym::coroutines, span, "yield syntax is experimental", diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index d8de447e5b4..a3ff02f5f69 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 dc23b1dce7b..5387880b6e6 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; @@ -1042,7 +1043,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { { add_feature_diagnostics( &mut err, - &self.tcx.sess.parse_sess, + &self.tcx.sess, sym::return_type_notation, ); } @@ -2309,7 +2310,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::ArrayLen::Infer(self.lower_node_id(c.id), self.lower_span(c.value.span)) } else { feature_err( - &self.tcx.sess.parse_sess, + &self.tcx.sess, sym::generic_arg_infer, c.value.span, "using `_` for array lengths is unstable", diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl index a10797626f1..6586ca5d36f 100644 --- a/compiler/rustc_ast_passes/messages.ftl +++ b/compiler/rustc_ast_passes/messages.ftl @@ -232,6 +232,9 @@ ast_passes_tilde_const_disallowed = `~const` is not allowed here .trait = this trait is not a `#[const_trait]`, so it cannot have `~const` trait bounds .trait_impl = this impl is not `const`, so it cannot have `~const` trait bounds .impl = inherent impls cannot have `~const` trait bounds + .trait_assoc_ty = associated types in non-`#[const_trait]` traits cannot have `~const` trait bounds + .trait_impl_assoc_ty = associated types in non-const impls cannot have `~const` trait bounds + .inherent_assoc_ty = inherent associated types cannot have `~const` trait bounds .object = trait objects cannot have `~const` trait bounds .item = this item cannot have `~const` trait bounds diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 7f78f687055..9ea5d1ed5fa 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -37,12 +37,17 @@ enum SelfSemantic { } /// What is the context that prevents using `~const`? +// FIXME(effects): Consider getting rid of this in favor of `errors::TildeConstReason`, they're +// almost identical. This gets rid of an abstraction layer which might be considered bad. enum DisallowTildeConstContext<'a> { TraitObject, Fn(FnKind<'a>), Trait(Span), TraitImpl(Span), Impl(Span), + TraitAssocTy(Span), + TraitImplAssocTy(Span), + InherentAssocTy(Span), Item, } @@ -316,6 +321,7 @@ impl<'a> AstValidator<'a> { constness: Const::No, polarity: ImplPolarity::Positive, trait_ref, + .. } = parent { Some(trait_ref.path.span.shrink_to_lo()) @@ -1286,6 +1292,15 @@ impl<'a> Visitor<'a> for AstValidator<'a> { // suggestion for moving such bounds to the assoc const fns if available. errors::TildeConstReason::Impl { span } } + &DisallowTildeConstContext::TraitAssocTy(span) => { + errors::TildeConstReason::TraitAssocTy { span } + } + &DisallowTildeConstContext::TraitImplAssocTy(span) => { + errors::TildeConstReason::TraitImplAssocTy { span } + } + &DisallowTildeConstContext::InherentAssocTy(span) => { + errors::TildeConstReason::InherentAssocTy { span } + } DisallowTildeConstContext::TraitObject => { errors::TildeConstReason::TraitObject } @@ -1483,13 +1498,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.check_item_named(item.ident, "const"); } + let parent_is_const = + self.outer_trait_or_trait_impl.as_ref().and_then(TraitOrTraitImpl::constness).is_some(); + match &item.kind { AssocItemKind::Fn(box Fn { sig, generics, body, .. }) - if self - .outer_trait_or_trait_impl - .as_ref() - .and_then(TraitOrTraitImpl::constness) - .is_some() + if parent_is_const || ctxt == AssocCtxt::Trait || matches!(sig.header.constness, Const::Yes(_)) => { @@ -1505,6 +1519,20 @@ impl<'a> Visitor<'a> for AstValidator<'a> { ); self.visit_fn(kind, item.span, item.id); } + AssocItemKind::Type(_) => { + let disallowed = (!parent_is_const).then(|| match self.outer_trait_or_trait_impl { + Some(TraitOrTraitImpl::Trait { .. }) => { + DisallowTildeConstContext::TraitAssocTy(item.span) + } + Some(TraitOrTraitImpl::TraitImpl { .. }) => { + DisallowTildeConstContext::TraitImplAssocTy(item.span) + } + None => DisallowTildeConstContext::InherentAssocTy(item.span), + }); + self.with_tilde_const(disallowed, |this| { + this.with_in_trait_impl(None, |this| visit::walk_assoc_item(this, item, ctxt)) + }) + } _ => self.with_in_trait_impl(None, |this| visit::walk_assoc_item(this, item, ctxt)), } } diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index fcf19ce52ec..e2b8e64b115 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -565,6 +565,8 @@ pub struct ConstBoundTraitObject { pub span: Span, } +// FIXME(effects): Consider making the note/reason the message of the diagnostic. +// FIXME(effects): Provide structured suggestions (e.g., add `const` / `#[const_trait]` here). #[derive(Diagnostic)] #[diag(ast_passes_tilde_const_disallowed)] pub struct TildeConstDisallowed { @@ -598,6 +600,21 @@ pub enum TildeConstReason { #[primary_span] span: Span, }, + #[note(ast_passes_trait_assoc_ty)] + TraitAssocTy { + #[primary_span] + span: Span, + }, + #[note(ast_passes_trait_impl_assoc_ty)] + TraitImplAssocTy { + #[primary_span] + span: Span, + }, + #[note(ast_passes_inherent_assoc_ty)] + InherentAssocTy { + #[primary_span] + span: Span, + }, #[note(ast_passes_object)] TraitObject, #[note(ast_passes_item)] diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 737e81eb6ec..192e458775a 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -17,14 +17,12 @@ use crate::errors; macro_rules! gate { ($visitor:expr, $feature:ident, $span:expr, $explain:expr) => {{ if !$visitor.features.$feature && !$span.allows_unstable(sym::$feature) { - feature_err(&$visitor.sess.parse_sess, sym::$feature, $span, $explain).emit(); + feature_err(&$visitor.sess, sym::$feature, $span, $explain).emit(); } }}; ($visitor:expr, $feature:ident, $span:expr, $explain:expr, $help:expr) => {{ if !$visitor.features.$feature && !$span.allows_unstable(sym::$feature) { - feature_err(&$visitor.sess.parse_sess, sym::$feature, $span, $explain) - .with_help($help) - .emit(); + feature_err(&$visitor.sess, sym::$feature, $span, $explain).with_help($help).emit(); } }}; } @@ -33,7 +31,7 @@ macro_rules! gate { macro_rules! gate_alt { ($visitor:expr, $has_feature:expr, $name:expr, $span:expr, $explain:expr) => {{ if !$has_feature && !$span.allows_unstable($name) { - feature_err(&$visitor.sess.parse_sess, $name, $span, $explain).emit(); + feature_err(&$visitor.sess, $name, $span, $explain).emit(); } }}; } @@ -45,7 +43,7 @@ macro_rules! gate_multi { let spans: Vec<_> = $spans.filter(|span| !span.allows_unstable(sym::$feature)).collect(); if !spans.is_empty() { - feature_err(&$visitor.sess.parse_sess, sym::$feature, spans, $explain).emit(); + feature_err(&$visitor.sess, sym::$feature, spans, $explain).emit(); } } }}; @@ -55,7 +53,7 @@ macro_rules! gate_multi { macro_rules! gate_legacy { ($visitor:expr, $feature:ident, $span:expr, $explain:expr) => {{ if !$visitor.features.$feature && !$span.allows_unstable(sym::$feature) { - feature_warn(&$visitor.sess.parse_sess, sym::$feature, $span, $explain); + feature_warn(&$visitor.sess, sym::$feature, $span, $explain); } }}; } @@ -91,14 +89,7 @@ impl<'a> PostExpansionVisitor<'a> { match abi::is_enabled(self.features, span, symbol_unescaped.as_str()) { Ok(()) => (), Err(abi::AbiDisabled::Unstable { feature, explain }) => { - feature_err_issue( - &self.sess.parse_sess, - feature, - span, - GateIssue::Language, - explain, - ) - .emit(); + feature_err_issue(&self.sess, feature, span, GateIssue::Language, explain).emit(); } Err(abi::AbiDisabled::Unrecognized) => { if self.sess.opts.pretty.map_or(true, |ppm| ppm.needs_hir()) { @@ -556,6 +547,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) { @@ -570,13 +562,8 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { if let Ok(snippet) = sm.span_to_snippet(span) && snippet == "!" { - feature_err( - &sess.parse_sess, - sym::never_patterns, - span, - "`!` patterns are experimental", - ) - .emit(); + feature_err(sess, sym::never_patterns, span, "`!` patterns are experimental") + .emit(); } else { let suggestion = span.shrink_to_hi(); sess.dcx().emit_err(errors::MatchArmWithNoBody { span, suggestion }); diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs index 43561a1c020..584f01e16c2 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_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index b3f601b7595..6b903be6e5e 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -9,7 +9,7 @@ use rustc_macros::HashStable_Generic; use rustc_session::config::ExpectedValues; use rustc_session::lint::builtin::UNEXPECTED_CFGS; use rustc_session::lint::BuiltinLintDiagnostics; -use rustc_session::parse::{feature_err, ParseSess}; +use rustc_session::parse::feature_err; use rustc_session::{RustcVersion, Session}; use rustc_span::hygiene::Transparency; use rustc_span::{symbol::sym, symbol::Symbol, Span}; @@ -518,15 +518,15 @@ pub struct Condition { /// Tests if a cfg-pattern matches the cfg set pub fn cfg_matches( cfg: &ast::MetaItem, - sess: &ParseSess, + sess: &Session, lint_node_id: NodeId, features: Option<&Features>, ) -> bool { eval_condition(cfg, sess, features, &mut |cfg| { try_gate_cfg(cfg.name, cfg.span, sess, features); - match sess.check_config.expecteds.get(&cfg.name) { + match sess.parse_sess.check_config.expecteds.get(&cfg.name) { Some(ExpectedValues::Some(values)) if !values.contains(&cfg.value) => { - sess.buffer_lint_with_diagnostic( + sess.parse_sess.buffer_lint_with_diagnostic( UNEXPECTED_CFGS, cfg.span, lint_node_id, @@ -541,8 +541,8 @@ pub fn cfg_matches( ), ); } - None if sess.check_config.exhaustive_names => { - sess.buffer_lint_with_diagnostic( + None if sess.parse_sess.check_config.exhaustive_names => { + sess.parse_sess.buffer_lint_with_diagnostic( UNEXPECTED_CFGS, cfg.span, lint_node_id, @@ -555,18 +555,18 @@ pub fn cfg_matches( } _ => { /* not unexpected */ } } - sess.config.contains(&(cfg.name, cfg.value)) + sess.parse_sess.config.contains(&(cfg.name, cfg.value)) }) } -fn try_gate_cfg(name: Symbol, span: Span, sess: &ParseSess, features: Option<&Features>) { +fn try_gate_cfg(name: Symbol, span: Span, sess: &Session, features: Option<&Features>) { let gate = find_gated_cfg(|sym| sym == name); if let (Some(feats), Some(gated_cfg)) = (features, gate) { gate_cfg(gated_cfg, span, sess, feats); } } -fn gate_cfg(gated_cfg: &GatedCfg, cfg_span: Span, sess: &ParseSess, features: &Features) { +fn gate_cfg(gated_cfg: &GatedCfg, cfg_span: Span, sess: &Session, features: &Features) { let (cfg, feature, has_feature) = gated_cfg; if !has_feature(features) && !cfg_span.allows_unstable(*feature) { let explain = format!("`cfg({cfg})` is experimental and subject to change"); @@ -594,11 +594,11 @@ fn parse_version(s: Symbol) -> Option<RustcVersion> { /// evaluate individual items. pub fn eval_condition( cfg: &ast::MetaItem, - sess: &ParseSess, + sess: &Session, features: Option<&Features>, eval: &mut impl FnMut(Condition) -> bool, ) -> bool { - let dcx = &sess.dcx; + let dcx = &sess.parse_sess.dcx; match &cfg.kind { ast::MetaItemKind::List(mis) if cfg.name_or_empty() == sym::version => { try_gate_cfg(sym::version, cfg.span, sess, features); @@ -626,7 +626,7 @@ pub fn eval_condition( }; // See https://github.com/rust-lang/rust/issues/64796#issuecomment-640851454 for details - if sess.assume_incomplete_release { + if sess.parse_sess.assume_incomplete_release { RustcVersion::CURRENT > min_version } else { RustcVersion::CURRENT >= min_version diff --git a/compiler/rustc_builtin_macros/src/cfg.rs b/compiler/rustc_builtin_macros/src/cfg.rs index 1bc2512a7b0..581d390992a 100644 --- a/compiler/rustc_builtin_macros/src/cfg.rs +++ b/compiler/rustc_builtin_macros/src/cfg.rs @@ -22,7 +22,7 @@ pub fn expand_cfg( Ok(cfg) => { let matches_cfg = attr::cfg_matches( &cfg, - &cx.sess.parse_sess, + &cx.sess, cx.current_expansion.lint_node_id, Some(cx.ecfg.features), ); diff --git a/compiler/rustc_builtin_macros/src/source_util.rs b/compiler/rustc_builtin_macros/src/source_util.rs index e7d7b4a7012..43d13569d1e 100644 --- a/compiler/rustc_builtin_macros/src/source_util.rs +++ b/compiler/rustc_builtin_macros/src/source_util.rs @@ -107,7 +107,7 @@ pub fn expand_include<'cx>( return DummyResult::any(sp); }; // The file will be added to the code map by the parser - let file = match resolve_path(&cx.sess.parse_sess, file.as_str(), sp) { + let file = match resolve_path(&cx.sess, file.as_str(), sp) { Ok(f) => f, Err(err) => { err.emit(); @@ -179,7 +179,7 @@ pub fn expand_include_str( let Some(file) = get_single_str_from_tts(cx, sp, tts, "include_str!") else { return DummyResult::any(sp); }; - let file = match resolve_path(&cx.sess.parse_sess, file.as_str(), sp) { + let file = match resolve_path(&cx.sess, file.as_str(), sp) { Ok(f) => f, Err(err) => { err.emit(); @@ -213,7 +213,7 @@ pub fn expand_include_bytes( let Some(file) = get_single_str_from_tts(cx, sp, tts, "include_bytes!") else { return DummyResult::any(sp); }; - let file = match resolve_path(&cx.sess.parse_sess, file.as_str(), sp) { + let file = match resolve_path(&cx.sess, file.as_str(), sp) { Ok(f) => f, Err(err) => { err.emit(); diff --git a/compiler/rustc_codegen_ssa/src/assert_module_sources.rs b/compiler/rustc_codegen_ssa/src/assert_module_sources.rs index 094a61d6e0d..a1daadce958 100644 --- a/compiler/rustc_codegen_ssa/src/assert_module_sources.rs +++ b/compiler/rustc_codegen_ssa/src/assert_module_sources.rs @@ -267,9 +267,12 @@ impl CguReuseTracker { fn check_expected_reuse(&self, sess: &Session) { if let Some(ref data) = self.data { - for (cgu_name, &(ref cgu_user_name, ref error_span, expected_reuse, comparison_kind)) in - &data.expected_reuse - { + let mut keys = data.expected_reuse.keys().collect::<Vec<_>>(); + keys.sort_unstable(); + for cgu_name in keys { + let &(ref cgu_user_name, ref error_span, expected_reuse, comparison_kind) = + data.expected_reuse.get(cgu_name).unwrap(); + if let Some(&actual_reuse) = data.actual_reuse.get(cgu_name) { let (error, at_least) = match comparison_kind { ComparisonKind::Exact => (expected_reuse != actual_reuse, false), diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index ace356ab153..959653c9326 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -554,6 +554,11 @@ fn link_staticlib<'a>( archive_builder_builder .extract_bundled_libs(path, tempdir.as_ref(), &relevant_libs) .unwrap_or_else(|e| sess.dcx().emit_fatal(e)); + + // We sort the libraries below + #[allow(rustc::potential_query_instability)] + let mut relevant_libs: Vec<Symbol> = relevant_libs.into_iter().collect(); + relevant_libs.sort_unstable(); for filename in relevant_libs { let joined = tempdir.as_ref().join(filename.as_str()); let path = joined.as_path(); @@ -2201,14 +2206,19 @@ fn linker_with_args<'a>( .iter() .find(|(ty, _)| *ty == crate_type) .expect("failed to find crate type in dependency format list"); - let native_libraries_from_nonstatics = codegen_results + + // We sort the libraries below + #[allow(rustc::potential_query_instability)] + let mut native_libraries_from_nonstatics = codegen_results .crate_info .native_libraries .iter() .filter_map(|(cnum, libraries)| { (dependency_linkage[cnum.as_usize() - 1] != Linkage::Static).then_some(libraries) }) - .flatten(); + .flatten() + .collect::<Vec<_>>(); + native_libraries_from_nonstatics.sort_unstable_by(|a, b| a.name.as_str().cmp(b.name.as_str())); for (raw_dylib_name, raw_dylib_imports) in collate_raw_dylibs(sess, native_libraries_from_nonstatics)? { @@ -2860,7 +2870,7 @@ fn add_dynamic_crate(cmd: &mut dyn Linker, sess: &Session, cratepath: &Path) { fn relevant_lib(sess: &Session, lib: &NativeLib) -> bool { match lib.cfg { - Some(ref cfg) => rustc_attr::cfg_matches(cfg, &sess.parse_sess, CRATE_NODE_ID, None), + Some(ref cfg) => rustc_attr::cfg_matches(cfg, sess, CRATE_NODE_ID, None), None => true, } } diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index cae7c40c5ad..2dba04e0bb7 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -319,6 +319,8 @@ fn exported_symbols_provider_local( let (_, cgus) = tcx.collect_and_partition_mono_items(()); + // The symbols created in this loop are sorted below it + #[allow(rustc::potential_query_instability)] for (mono_item, data) in cgus.iter().flat_map(|cgu| cgu.items().iter()) { if data.linkage != Linkage::External { // We can only re-use things with external linkage, otherwise diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 0ad4af968db..098ea1b793c 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -912,17 +912,22 @@ impl CrateInfo { }) .collect(); let prefix = if target.is_like_windows && target.arch == "x86" { "_" } else { "" }; + + // This loop only adds new items to values of the hash map, so the order in which we + // iterate over the values is not important. + #[allow(rustc::potential_query_instability)] info.linked_symbols .iter_mut() .filter(|(crate_type, _)| { !matches!(crate_type, CrateType::Rlib | CrateType::Staticlib) }) .for_each(|(_, linked_symbols)| { - linked_symbols.extend( - missing_weak_lang_items - .iter() - .map(|item| (format!("{prefix}{item}"), SymbolExportKind::Text)), - ); + let mut symbols = missing_weak_lang_items + .iter() + .map(|item| (format!("{prefix}{item}"), SymbolExportKind::Text)) + .collect::<Vec<_>>(); + symbols.sort_unstable_by(|a, b| a.0.cmp(&b.0)); + linked_symbols.extend(symbols); if tcx.allocator_kind(()).is_some() { // At least one crate needs a global allocator. This crate may be placed // after the crate that defines it in the linker order, in which case some diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 36d7234a6ea..198b7ac4170 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -155,7 +155,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { Some([item]) if item.has_name(sym::linker) => { if !tcx.features().used_with_arg { feature_err( - &tcx.sess.parse_sess, + &tcx.sess, sym::used_with_arg, attr.span, "`#[used(linker)]` is currently unstable", @@ -167,7 +167,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { Some([item]) if item.has_name(sym::compiler) => { if !tcx.features().used_with_arg { feature_err( - &tcx.sess.parse_sess, + &tcx.sess, sym::used_with_arg, attr.span, "`#[used(compiler)]` is currently unstable", @@ -251,7 +251,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { && !attr.span.allows_unstable(sym::closure_track_caller) { feature_err( - &tcx.sess.parse_sess, + &tcx.sess, sym::closure_track_caller, attr.span, "`#[track_caller]` on closures is currently unstable", @@ -304,7 +304,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { // `#[target_feature]` on `main` and `start`. } else if !tcx.features().target_feature_11 { feature_err( - &tcx.sess.parse_sess, + &tcx.sess, sym::target_feature_11, attr.span, "`#[target_feature(..)]` can only be applied to `unsafe` functions", diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 99280fdba7c..8f5421823a3 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -11,7 +11,6 @@ #![feature(strict_provenance)] #![feature(try_blocks)] #![recursion_limit = "256"] -#![allow(rustc::potential_query_instability)] //! This crate contains codegen code that is used by all codegen backends (LLVM and others). //! The backend-agnostic functions of this crate use functions defined in various traits that diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index 0fef6bc110e..3694e41a0e0 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -82,7 +82,7 @@ pub fn from_target_feature( }; if !allowed { feature_err( - &tcx.sess.parse_sess, + &tcx.sess, feature_gate.unwrap(), item.span(), format!("the target feature `{feature}` is currently unstable"), diff --git a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs index 02952872a93..327c91731bf 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs @@ -64,7 +64,7 @@ impl<'tcx> NonConstOp<'tcx> for FloatingPointOp { fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { feature_err( - &ccx.tcx.sess.parse_sess, + &ccx.tcx.sess, sym::const_fn_floating_point_arithmetic, span, format!("floating point arithmetic is not allowed in {}s", ccx.const_kind()), @@ -553,7 +553,7 @@ impl<'tcx> NonConstOp<'tcx> for RawMutPtrDeref { fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { feature_err( - &ccx.tcx.sess.parse_sess, + &ccx.tcx.sess, sym::const_mut_refs, span, format!("dereferencing raw mutable pointers in {}s is unstable", ccx.const_kind(),), @@ -624,7 +624,7 @@ pub mod ty { fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { feature_err( - &ccx.tcx.sess.parse_sess, + &ccx.tcx.sess, sym::const_mut_refs, span, format!("mutable references are not allowed in {}s", ccx.const_kind()), diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 8c2752af659..63391a0faa6 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -865,10 +865,6 @@ impl DiagCtxt { /// directly). #[track_caller] pub fn delayed_bug(&self, msg: impl Into<DiagnosticMessage>) -> ErrorGuaranteed { - let treat_next_err_as_bug = self.inner.borrow().treat_next_err_as_bug(); - if treat_next_err_as_bug { - self.bug(msg); - } DiagnosticBuilder::<ErrorGuaranteed>::new(self, DelayedBug(DelayedBugKind::Normal), msg) .emit() } @@ -883,10 +879,6 @@ impl DiagCtxt { sp: impl Into<MultiSpan>, msg: impl Into<DiagnosticMessage>, ) -> ErrorGuaranteed { - let treat_next_err_as_bug = self.inner.borrow().treat_next_err_as_bug(); - if treat_next_err_as_bug { - self.span_bug(sp, msg); - } DiagnosticBuilder::<ErrorGuaranteed>::new(self, DelayedBug(DelayedBugKind::Normal), msg) .with_span(sp) .emit() @@ -1259,10 +1251,6 @@ impl DiagCtxtInner { } fn emit_diagnostic(&mut self, mut diagnostic: Diagnostic) -> Option<ErrorGuaranteed> { - if matches!(diagnostic.level, Error | Fatal) && self.treat_next_err_as_bug() { - diagnostic.level = Bug; - } - // The `LintExpectationId` can be stable or unstable depending on when it was created. // Diagnostics created before the definition of `HirId`s are unstable and can not yet // be stored. Instead, they are buffered until the `LintExpectationId` is replaced by @@ -1298,6 +1286,12 @@ impl DiagCtxtInner { _ => {} } + // This must come after the possible promotion of `DelayedBug` to + // `Error` above. + if matches!(diagnostic.level, Error | Fatal) && self.treat_next_err_as_bug() { + diagnostic.level = Bug; + } + if diagnostic.has_future_breakage() { // Future breakages aren't emitted if they're Level::Allow, // but they still need to be constructed and stashed below, @@ -1387,20 +1381,14 @@ impl DiagCtxtInner { } fn treat_err_as_bug(&self) -> bool { - self.flags.treat_err_as_bug.is_some_and(|c| { - self.err_count + self.lint_err_count + self.delayed_bug_count() >= c.get() - }) + self.flags.treat_err_as_bug.is_some_and(|c| self.err_count + self.lint_err_count >= c.get()) } // Use this one before incrementing `err_count`. fn treat_next_err_as_bug(&self) -> bool { - self.flags.treat_err_as_bug.is_some_and(|c| { - self.err_count + self.lint_err_count + self.delayed_bug_count() + 1 >= c.get() - }) - } - - fn delayed_bug_count(&self) -> usize { - self.span_delayed_bugs.len() + self.good_path_delayed_bugs.len() + self.flags + .treat_err_as_bug + .is_some_and(|c| self.err_count + self.lint_err_count + 1 >= c.get()) } fn has_errors(&self) -> bool { @@ -1412,7 +1400,7 @@ impl DiagCtxtInner { } fn flush_delayed(&mut self, kind: DelayedBugKind) { - let (bugs, explanation) = match kind { + let (bugs, note1) = match kind { DelayedBugKind::Normal => ( std::mem::take(&mut self.span_delayed_bugs), "no errors encountered even though `span_delayed_bug` issued", @@ -1422,6 +1410,7 @@ impl DiagCtxtInner { "no warnings or errors encountered even though `good_path_delayed_bugs` issued", ), }; + let note2 = "those delayed bugs will now be shown as internal compiler errors"; if bugs.is_empty() { return; @@ -1447,8 +1436,11 @@ impl DiagCtxtInner { if i == 0 { // Put the overall explanation before the `DelayedBug`s, to - // frame them better (e.g. separate warnings from them). - self.emit_diagnostic(Diagnostic::new(Bug, explanation)); + // frame them better (e.g. separate warnings from them). Also, + // make it a note so it doesn't count as an error, because that + // could trigger `-Ztreat-err-as-bug`, which we don't want. + self.emit_diagnostic(Diagnostic::new(Note, note1)); + self.emit_diagnostic(Diagnostic::new(Note, note2)); } let mut bug = @@ -1474,22 +1466,12 @@ impl DiagCtxtInner { fn panic_if_treat_err_as_bug(&self) { if self.treat_err_as_bug() { - match ( - self.err_count + self.lint_err_count, - self.delayed_bug_count(), - self.flags.treat_err_as_bug.map(|c| c.get()).unwrap(), - ) { - (1, 0, 1) => panic!("aborting due to `-Z treat-err-as-bug=1`"), - (0, 1, 1) => panic!("aborting due delayed bug with `-Z treat-err-as-bug=1`"), - (count, delayed_count, val) => { - if delayed_count > 0 { - panic!( - "aborting after {count} errors and {delayed_count} delayed bugs due to `-Z treat-err-as-bug={val}`", - ) - } else { - panic!("aborting after {count} errors due to `-Z treat-err-as-bug={val}`") - } - } + let n = self.flags.treat_err_as_bug.map(|c| c.get()).unwrap(); + assert_eq!(n, self.err_count + self.lint_err_count); + if n == 1 { + panic!("aborting due to `-Z treat-err-as-bug=1`"); + } else { + panic!("aborting after {n} errors due to `-Z treat-err-as-bug={n}`"); } } } diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index e87f2306bc7..0a1c4430397 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -1150,7 +1150,7 @@ impl<'a> ExtCtxt<'a> { /// /// This unifies the logic used for resolving `include_X!`. pub fn resolve_path( - parse_sess: &ParseSess, + parse_sess: &Session, path: impl Into<PathBuf>, span: Span, ) -> PResult<'_, PathBuf> { @@ -1166,7 +1166,7 @@ pub fn resolve_path( .expect("attempting to resolve a file path in an external file"), FileName::DocTest(path, _) => path, other => { - return Err(parse_sess.dcx.create_err(errors::ResolveRelativePath { + return Err(parse_sess.dcx().create_err(errors::ResolveRelativePath { span, path: parse_sess.source_map().filename_for_diagnostics(&other).to_string(), })); @@ -1390,7 +1390,7 @@ pub fn parse_macro_name_and_helper_attrs( /// asserts in old versions of those crates and their wide use in the ecosystem. /// See issue #73345 for more details. /// FIXME(#73933): Remove this eventually. -fn pretty_printing_compatibility_hack(item: &Item, sess: &ParseSess) -> bool { +fn pretty_printing_compatibility_hack(item: &Item, sess: &Session) -> bool { let name = item.ident.name; if name == sym::ProceduralMasqueradeDummyType { if let ast::ItemKind::Enum(enum_def, _) = &item.kind { @@ -1418,7 +1418,7 @@ fn pretty_printing_compatibility_hack(item: &Item, sess: &ParseSess) -> bool { }; if crate_matches { - sess.buffer_lint_with_diagnostic( + sess.parse_sess.buffer_lint_with_diagnostic( PROC_MACRO_BACK_COMPAT, item.ident.span, ast::CRATE_NODE_ID, @@ -1439,7 +1439,7 @@ fn pretty_printing_compatibility_hack(item: &Item, sess: &ParseSess) -> bool { false } -pub(crate) fn ann_pretty_printing_compatibility_hack(ann: &Annotatable, sess: &ParseSess) -> bool { +pub(crate) fn ann_pretty_printing_compatibility_hack(ann: &Annotatable, sess: &Session) -> bool { let item = match ann { Annotatable::Item(item) => item, Annotatable::Stmt(stmt) => match &stmt.kind { @@ -1451,7 +1451,7 @@ pub(crate) fn ann_pretty_printing_compatibility_hack(ann: &Annotatable, sess: &P pretty_printing_compatibility_hack(item, sess) } -pub(crate) fn nt_pretty_printing_compatibility_hack(nt: &Nonterminal, sess: &ParseSess) -> bool { +pub(crate) fn nt_pretty_printing_compatibility_hack(nt: &Nonterminal, sess: &Session) -> bool { let item = match nt { Nonterminal::NtItem(item) => item, Nonterminal::NtStmt(stmt) => match &stmt.kind { diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index d015d779963..f574e81e905 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -256,12 +256,7 @@ impl<'a> StripUnconfigured<'a> { ); } - if !attr::cfg_matches( - &cfg_predicate, - &self.sess.parse_sess, - self.lint_node_id, - self.features, - ) { + if !attr::cfg_matches(&cfg_predicate, &self.sess, self.lint_node_id, self.features) { return vec![]; } @@ -369,12 +364,7 @@ impl<'a> StripUnconfigured<'a> { }; ( parse_cfg(&meta_item, self.sess).map_or(true, |meta_item| { - attr::cfg_matches( - meta_item, - &self.sess.parse_sess, - self.lint_node_id, - self.features, - ) + attr::cfg_matches(meta_item, &self.sess, self.lint_node_id, self.features) }), Some(meta_item), ) @@ -385,7 +375,7 @@ impl<'a> StripUnconfigured<'a> { pub(crate) fn maybe_emit_expr_attr_err(&self, attr: &Attribute) { if self.features.is_some_and(|features| !features.stmt_expr_attributes) { let mut err = feature_err( - &self.sess.parse_sess, + &self.sess, sym::stmt_expr_attributes, attr.span, "attributes on expressions are experimental", diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index c39a3dce34e..9c411be9ff9 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -30,8 +30,8 @@ use rustc_parse::parser::{ use rustc_parse::validate_attr; use rustc_session::lint::builtin::{UNUSED_ATTRIBUTES, UNUSED_DOC_COMMENTS}; use rustc_session::lint::BuiltinLintDiagnostics; -use rustc_session::parse::{feature_err, ParseSess}; -use rustc_session::Limit; +use rustc_session::parse::feature_err; +use rustc_session::{Limit, Session}; use rustc_span::symbol::{sym, Ident}; use rustc_span::{FileName, LocalExpnId, Span}; @@ -800,7 +800,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { return; } feature_err( - &self.cx.sess.parse_sess, + &self.cx.sess, sym::proc_macro_hygiene, span, format!("custom attributes cannot be applied to {kind}"), @@ -810,7 +810,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { fn gate_proc_macro_input(&self, annotatable: &Annotatable) { struct GateProcMacroInput<'a> { - parse_sess: &'a ParseSess, + sess: &'a Session, } impl<'ast, 'a> Visitor<'ast> for GateProcMacroInput<'a> { @@ -820,7 +820,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { if !matches!(mod_kind, ModKind::Loaded(_, Inline::Yes, _)) => { feature_err( - self.parse_sess, + self.sess, sym::proc_macro_hygiene, item.span, "non-inline modules in proc macro input are unstable", @@ -835,8 +835,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } if !self.cx.ecfg.features.proc_macro_hygiene { - annotatable - .visit_with(&mut GateProcMacroInput { parse_sess: &self.cx.sess.parse_sess }); + annotatable.visit_with(&mut GateProcMacroInput { sess: &self.cx.sess }); } } diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index a56c980791a..363b52aef8a 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -477,14 +477,14 @@ pub fn compile_declarative_macro( let tt = mbe::quoted::parse( &TokenStream::new(vec![tt.clone()]), true, - &sess.parse_sess, + sess, def.id, features, edition, ) .pop() .unwrap(); - valid &= check_lhs_nt_follows(&sess.parse_sess, def, &tt); + valid &= check_lhs_nt_follows(sess, def, &tt); return tt; } sess.dcx().span_bug(def.span, "wrong-structured lhs") @@ -501,7 +501,7 @@ pub fn compile_declarative_macro( return mbe::quoted::parse( &TokenStream::new(vec![tt.clone()]), false, - &sess.parse_sess, + sess, def.id, features, edition, @@ -516,12 +516,12 @@ pub fn compile_declarative_macro( }; for rhs in &rhses { - valid &= check_rhs(&sess.parse_sess, rhs); + valid &= check_rhs(sess, rhs); } // don't abort iteration early, so that errors for multiple lhses can be reported for lhs in &lhses { - valid &= check_lhs_no_empty_seq(&sess.parse_sess, slice::from_ref(lhs)); + valid &= check_lhs_no_empty_seq(sess, slice::from_ref(lhs)); } valid &= macro_check::check_meta_variables(&sess.parse_sess, def.id, def.span, &lhses, &rhses); @@ -588,21 +588,21 @@ pub fn compile_declarative_macro( (mk_syn_ext(expander), rule_spans) } -fn check_lhs_nt_follows(sess: &ParseSess, def: &ast::Item, lhs: &mbe::TokenTree) -> bool { +fn check_lhs_nt_follows(sess: &Session, def: &ast::Item, lhs: &mbe::TokenTree) -> bool { // lhs is going to be like TokenTree::Delimited(...), where the // entire lhs is those tts. Or, it can be a "bare sequence", not wrapped in parens. if let mbe::TokenTree::Delimited(.., delimited) = lhs { check_matcher(sess, def, &delimited.tts) } else { let msg = "invalid macro matcher; matchers must be contained in balanced delimiters"; - sess.dcx.span_err(lhs.span(), msg); + sess.dcx().span_err(lhs.span(), msg); false } // we don't abort on errors on rejection, the driver will do that for us // after parsing/expansion. we can report every error in every macro this way. } -fn is_empty_token_tree(sess: &ParseSess, seq: &mbe::SequenceRepetition) -> bool { +fn is_empty_token_tree(sess: &Session, seq: &mbe::SequenceRepetition) -> bool { if seq.separator.is_some() { false } else { @@ -621,7 +621,7 @@ fn is_empty_token_tree(sess: &ParseSess, seq: &mbe::SequenceRepetition) -> bool iter.next(); } let span = t.span.to(now.span); - sess.dcx.span_note(span, "doc comments are ignored in matcher position"); + sess.dcx().span_note(span, "doc comments are ignored in matcher position"); } mbe::TokenTree::Sequence(_, sub_seq) if (sub_seq.kleene.op == mbe::KleeneOp::ZeroOrMore @@ -635,7 +635,7 @@ fn is_empty_token_tree(sess: &ParseSess, seq: &mbe::SequenceRepetition) -> bool /// Checks that the lhs contains no repetition which could match an empty token /// tree, because then the matcher would hang indefinitely. -fn check_lhs_no_empty_seq(sess: &ParseSess, tts: &[mbe::TokenTree]) -> bool { +fn check_lhs_no_empty_seq(sess: &Session, tts: &[mbe::TokenTree]) -> bool { use mbe::TokenTree; for tt in tts { match tt { @@ -651,7 +651,7 @@ fn check_lhs_no_empty_seq(sess: &ParseSess, tts: &[mbe::TokenTree]) -> bool { TokenTree::Sequence(span, seq) => { if is_empty_token_tree(sess, seq) { let sp = span.entire(); - sess.dcx.span_err(sp, "repetition matches empty token tree"); + sess.dcx().span_err(sp, "repetition matches empty token tree"); return false; } if !check_lhs_no_empty_seq(sess, &seq.tts) { @@ -664,22 +664,22 @@ fn check_lhs_no_empty_seq(sess: &ParseSess, tts: &[mbe::TokenTree]) -> bool { true } -fn check_rhs(sess: &ParseSess, rhs: &mbe::TokenTree) -> bool { +fn check_rhs(sess: &Session, rhs: &mbe::TokenTree) -> bool { match *rhs { mbe::TokenTree::Delimited(..) => return true, _ => { - sess.dcx.span_err(rhs.span(), "macro rhs must be delimited"); + sess.dcx().span_err(rhs.span(), "macro rhs must be delimited"); } } false } -fn check_matcher(sess: &ParseSess, def: &ast::Item, matcher: &[mbe::TokenTree]) -> bool { +fn check_matcher(sess: &Session, def: &ast::Item, matcher: &[mbe::TokenTree]) -> bool { let first_sets = FirstSets::new(matcher); let empty_suffix = TokenSet::empty(); - let err = sess.dcx.err_count(); + let err = sess.dcx().err_count(); check_matcher_core(sess, def, &first_sets, matcher, &empty_suffix); - err == sess.dcx.err_count() + err == sess.dcx().err_count() } fn has_compile_error_macro(rhs: &mbe::TokenTree) -> bool { @@ -1014,7 +1014,7 @@ impl<'tt> TokenSet<'tt> { // Requires that `first_sets` is pre-computed for `matcher`; // see `FirstSets::new`. fn check_matcher_core<'tt>( - sess: &ParseSess, + sess: &Session, def: &ast::Item, first_sets: &FirstSets<'tt>, matcher: &'tt [mbe::TokenTree], @@ -1139,7 +1139,7 @@ fn check_matcher_core<'tt>( name, Some(NonterminalKind::PatParam { inferred: false }), )); - sess.buffer_lint_with_diagnostic( + sess.parse_sess.buffer_lint_with_diagnostic( RUST_2021_INCOMPATIBLE_OR_PATTERNS, span, ast::CRATE_NODE_ID, @@ -1158,7 +1158,7 @@ fn check_matcher_core<'tt>( }; let sp = next_token.span(); - let mut err = sess.dcx.struct_span_err( + let mut err = sess.dcx().struct_span_err( sp, format!( "`${name}:{frag}` {may_be} followed by `{next}`, which \ @@ -1172,7 +1172,7 @@ fn check_matcher_core<'tt>( err.span_label(sp, format!("not allowed after `{kind}` fragments")); if kind == NonterminalKind::PatWithOr - && sess.edition.at_least_rust_2021() + && sess.parse_sess.edition.at_least_rust_2021() && next_token.is_token(&BinOp(token::BinOpToken::Or)) { let suggestion = quoted_tt_to_string(&TokenTree::MetaVarDecl( diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs index 889f43ed203..4824b67d277 100644 --- a/compiler/rustc_expand/src/mbe/quoted.rs +++ b/compiler/rustc_expand/src/mbe/quoted.rs @@ -5,7 +5,8 @@ use rustc_ast::token::{self, Delimiter, Token}; use rustc_ast::{tokenstream, NodeId}; use rustc_ast_pretty::pprust; use rustc_feature::Features; -use rustc_session::parse::{feature_err, ParseSess}; +use rustc_session::parse::feature_err; +use rustc_session::Session; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::edition::Edition; @@ -38,7 +39,7 @@ const VALID_FRAGMENT_NAMES_MSG: &str = "valid fragment specifiers are \ pub(super) fn parse( input: &tokenstream::TokenStream, parsing_patterns: bool, - sess: &ParseSess, + sess: &Session, node_id: NodeId, features: &Features, edition: Edition, @@ -84,7 +85,7 @@ pub(super) fn parse( "invalid fragment specifier `{}`", frag.name ); - sess.dcx + sess.dcx() .struct_span_err(span, msg) .with_help(VALID_FRAGMENT_NAMES_MSG) .emit(); @@ -113,7 +114,7 @@ pub(super) fn parse( } /// Asks for the `macro_metavar_expr` feature if it is not already declared -fn maybe_emit_macro_metavar_expr_feature(features: &Features, sess: &ParseSess, span: Span) { +fn maybe_emit_macro_metavar_expr_feature(features: &Features, sess: &Session, span: Span) { if !features.macro_metavar_expr { let msg = "meta-variable expressions are unstable"; feature_err(sess, sym::macro_metavar_expr, span, msg).emit(); @@ -138,7 +139,7 @@ fn parse_tree<'a>( tree: &'a tokenstream::TokenTree, outer_trees: &mut impl Iterator<Item = &'a tokenstream::TokenTree>, parsing_patterns: bool, - sess: &ParseSess, + sess: &Session, node_id: NodeId, features: &Features, edition: Edition, @@ -174,7 +175,8 @@ fn parse_tree<'a>( // The delimiter is `{`. This indicates the beginning // of a meta-variable expression (e.g. `${count(ident)}`). // Try to parse the meta-variable expression. - match MetaVarExpr::parse(tts, delim_span.entire(), sess) { + match MetaVarExpr::parse(tts, delim_span.entire(), &sess.parse_sess) + { Err(err) => { err.emit(); // Returns early the same read `$` to avoid spanning @@ -195,7 +197,7 @@ fn parse_tree<'a>( _ => { let tok = pprust::token_kind_to_string(&token::OpenDelim(delim)); let msg = format!("expected `(` or `{{`, found `{tok}`"); - sess.dcx.span_err(delim_span.entire(), msg); + sess.dcx().span_err(delim_span.entire(), msg); } } } @@ -244,7 +246,7 @@ fn parse_tree<'a>( Some(tokenstream::TokenTree::Token(token, _)) => { let msg = format!("expected identifier, found `{}`", pprust::token_to_string(token),); - sess.dcx.span_err(token.span, msg); + sess.dcx().span_err(token.span, msg); TokenTree::MetaVar(token.span, Ident::empty()) } @@ -313,7 +315,7 @@ fn parse_kleene_op<'a>( fn parse_sep_and_kleene_op<'a>( input: &mut impl Iterator<Item = &'a tokenstream::TokenTree>, span: Span, - sess: &ParseSess, + sess: &Session, ) -> (Option<Token>, KleeneToken) { // We basically look at two token trees here, denoted as #1 and #2 below let span = match parse_kleene_op(input, span) { @@ -325,7 +327,7 @@ fn parse_sep_and_kleene_op<'a>( // #2 is the `?` Kleene op, which does not take a separator (error) Ok(Ok((KleeneOp::ZeroOrOne, span))) => { // Error! - sess.dcx.span_err( + sess.dcx().span_err( token.span, "the `?` macro repetition operator does not take a separator", ); @@ -346,7 +348,7 @@ fn parse_sep_and_kleene_op<'a>( }; // If we ever get to this point, we have experienced an "unexpected token" error - sess.dcx.span_err(span, "expected one of: `*`, `+`, or `?`"); + sess.dcx().span_err(span, "expected one of: `*`, `+`, or `?`"); // Return a dummy (None, KleeneToken::new(KleeneOp::ZeroOrMore, span)) @@ -355,9 +357,10 @@ fn parse_sep_and_kleene_op<'a>( // `$$` or a meta-variable is the lhs of a macro but shouldn't. // // For example, `macro_rules! foo { ( ${length()} ) => {} }` -fn span_dollar_dollar_or_metavar_in_the_lhs_err(sess: &ParseSess, token: &Token) { - sess.dcx.span_err(token.span, format!("unexpected token: {}", pprust::token_to_string(token))); - sess.dcx.span_note( +fn span_dollar_dollar_or_metavar_in_the_lhs_err(sess: &Session, token: &Token) { + sess.dcx() + .span_err(token.span, format!("unexpected token: {}", pprust::token_to_string(token))); + sess.dcx().span_note( token.span, "`$$` and meta-variable expressions are not allowed inside macro parameter definitions", ); diff --git a/compiler/rustc_expand/src/proc_macro.rs b/compiler/rustc_expand/src/proc_macro.rs index a1d21361957..2233cad2e63 100644 --- a/compiler/rustc_expand/src/proc_macro.rs +++ b/compiler/rustc_expand/src/proc_macro.rs @@ -119,7 +119,7 @@ impl MultiItemModifier for DeriveProcMacro { // We need special handling for statement items // (e.g. `fn foo() { #[derive(Debug)] struct Bar; }`) let is_stmt = matches!(item, Annotatable::Stmt(..)); - let hack = crate::base::ann_pretty_printing_compatibility_hack(&item, &ecx.sess.parse_sess); + let hack = crate::base::ann_pretty_printing_compatibility_hack(&item, &ecx.sess); let input = if hack { let nt = match item { Annotatable::Item(item) => token::NtItem(item), diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index 6392894fea2..3a78bd94505 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -258,7 +258,7 @@ impl FromInternal<(TokenStream, &mut Rustc<'_, '_>)> for Vec<TokenTree<TokenStre // represented as a delimited group. // FIXME: It needs to be removed, but there are some // compatibility issues (see #73345). - if crate::base::nt_pretty_printing_compatibility_hack(&nt.0, rustc.sess()) { + if crate::base::nt_pretty_printing_compatibility_hack(&nt.0, rustc.ecx.sess) { trees.extend(Self::from_internal((stream, rustc))); } else { trees.push(TokenTree::Group(Group { diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 58ac9668da5..6b347f7035a 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 dd3633b6b4f..adc09025809 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 6a17668ad17..432c9c12cbf 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/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs index 7b23b74f829..bfe88df4e1a 100644 --- a/compiler/rustc_hir_analysis/src/astconv/errors.rs +++ b/compiler/rustc_hir_analysis/src/astconv/errors.rs @@ -59,7 +59,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { if trait_segment.args().parenthesized == hir::GenericArgsParentheses::ParenSugar { // For now, require that parenthetical notation be used only with `Fn()` etc. feature_err( - &self.tcx().sess.parse_sess, + &self.tcx().sess, sym::unboxed_closures, span, "parenthetical notation is only stable when used with `Fn`-family traits", @@ -75,7 +75,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { if trait_segment.args().parenthesized != hir::GenericArgsParentheses::ParenSugar { // For now, require that parenthetical notation be used only with `Fn()` etc. let mut err = feature_err( - &sess.parse_sess, + sess, sym::unboxed_closures, span, "the precise format of `Fn`-family traits' type parameters is subject to change", diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 2886ec21320..9f4f1413650 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; @@ -2322,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)] @@ -2329,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 }) @@ -2520,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. @@ -2543,7 +2659,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self.suggest_trait_fn_ty_for_impl_fn_infer(hir_id, Some(i)) { infer_replacements.push((a.span, suggested_ty.to_string())); - return suggested_ty; + return Ty::new_error_with_message( + self.tcx(), + a.span, + suggested_ty.to_string(), + ); } } @@ -2561,7 +2681,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self.suggest_trait_fn_ty_for_impl_fn_infer(hir_id, None) { infer_replacements.push((output.span, suggested_ty.to_string())); - suggested_ty + Ty::new_error_with_message(self.tcx(), output.span, suggested_ty.to_string()) } else { visitor.visit_ty(output); self.ast_ty_to_ty(output) diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 6265ddafef0..77914802bf7 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -996,7 +996,7 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>) if adt.is_union() && !tcx.features().transparent_unions { feature_err( - &tcx.sess.parse_sess, + &tcx.sess, sym::transparent_unions, tcx.def_span(adt.did()), "transparent unions are unstable", @@ -1128,7 +1128,7 @@ fn check_enum(tcx: TyCtxt<'_>, def_id: LocalDefId) { if repr_type_ty == tcx.types.i128 || repr_type_ty == tcx.types.u128 { if !tcx.features().repr128 { feature_err( - &tcx.sess.parse_sess, + &tcx.sess, sym::repr128, tcx.def_span(def_id), "repr with 128-bit type is unstable", diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index 3b05eaedf34..28c8f846c23 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -293,7 +293,7 @@ fn default_body_is_unstable( rustc_session::parse::add_feature_diagnostics_for_issue( &mut err, - &tcx.sess.parse_sess, + &tcx.sess, feature, rustc_feature::GateIssue::Library(issue), false, diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 59c72227144..4772bae58c4 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1591,7 +1591,7 @@ fn check_method_receiver<'tcx>( return Err(if receiver_is_valid(wfcx, span, receiver_ty, self_ty, true) { // Report error; would have worked with `arbitrary_self_types`. feature_err( - &tcx.sess.parse_sess, + &tcx.sess, sym::arbitrary_self_types, span, format!( diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 3d8390d1946..4f049f699e6 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -1189,12 +1189,13 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { && !self.tcx.asyncness(lifetime_ref.hir_id.owner.def_id).is_async() && !self.tcx.features().anonymous_lifetime_in_impl_trait { - let mut diag = rustc_session::parse::feature_err( - &self.tcx.sess.parse_sess, - sym::anonymous_lifetime_in_impl_trait, - lifetime_ref.ident.span, - "anonymous lifetimes in `impl Trait` are unstable", - ); + let mut diag: rustc_errors::DiagnosticBuilder<'_> = + rustc_session::parse::feature_err( + &self.tcx.sess, + sym::anonymous_lifetime_in_impl_trait, + lifetime_ref.ident.span, + "anonymous lifetimes in `impl Trait` are unstable", + ); if let Some(generics) = self.tcx.hir().get_generics(lifetime_ref.hir_id.owner.def_id) diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index b936b0c0805..bfa9dc42422 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -639,7 +639,7 @@ fn check_feature_inherent_assoc_ty(tcx: TyCtxt<'_>, span: Span) { use rustc_session::parse::feature_err; use rustc_span::symbol::sym; feature_err( - &tcx.sess.parse_sess, + &tcx.sess, sym::inherent_associated_types, span, "inherent associated types are unstable", diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 4f22da4ba3b..f14390b77c6 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -1501,3 +1501,13 @@ pub enum RefOfMutStaticSugg { var: String, }, } + +#[derive(Diagnostic)] +#[diag(hir_analysis_not_supported_delegation)] +pub struct NotSupportedDelegation<'a> { + #[primary_span] + pub span: Span, + pub descr: &'a str, + #[label] + pub callee_span: Span, +} diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index dfc54ac5b23..f5abb7261c0 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -116,7 +116,8 @@ use rustc_hir::def::DefKind; rustc_fluent_macro::fluent_messages! { "../messages.ftl" } fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: Abi, span: Span) { - const CONVENTIONS_UNSTABLE: &str = "`C`, `cdecl`, `aapcs`, `win64`, `sysv64` or `efiapi`"; + const CONVENTIONS_UNSTABLE: &str = + "`C`, `cdecl`, `system`, `aapcs`, `win64`, `sysv64` or `efiapi`"; const CONVENTIONS_STABLE: &str = "`C` or `cdecl`"; const UNSTABLE_EXPLAIN: &str = "using calling conventions other than `C` or `cdecl` for varargs functions is unstable"; @@ -133,13 +134,8 @@ fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: Abi // Using this ABI would be ok, if the feature for additional ABI support was enabled. // Return CONVENTIONS_STABLE, because we want the other error to look the same. (false, true) => { - feature_err( - &tcx.sess.parse_sess, - sym::extended_varargs_abi_support, - span, - UNSTABLE_EXPLAIN, - ) - .emit(); + feature_err(&tcx.sess, sym::extended_varargs_abi_support, span, UNSTABLE_EXPLAIN) + .emit(); CONVENTIONS_STABLE } diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 1eaec997053..d36e0892d19 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/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 0b266202b26..e9d373119fa 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -704,7 +704,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { if has_unsized_tuple_coercion && !self.tcx.features().unsized_tuple_coercion { feature_err( - &self.tcx.sess.parse_sess, + &self.tcx.sess, sym::unsized_tuple_coercion, self.cause.span, "unsized tuple coercion is not stable enough for use and is subject to change", diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index fdad998c451..af47455c16d 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1865,7 +1865,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (ty::Adt(adt, _), ty::Adt(base_adt, _)) if adt == base_adt); if self.tcx.sess.is_nightly_build() && same_adt { feature_err( - &self.tcx.sess.parse_sess, + &self.tcx.sess, sym::type_changing_struct_update, base_expr.span, "type changing struct updating is experimental", @@ -3262,7 +3262,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if !self.tcx.features().offset_of_enum { rustc_session::parse::feature_err( - &self.tcx.sess.parse_sess, + &self.tcx.sess, sym::offset_of_enum, ident.span, "using enums in offset_of is experimental", diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index 09313cd9738..e60e3ffeaa7 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -84,7 +84,7 @@ impl<'tcx> InferCtxt<'tcx> { selection_cache: self.selection_cache.clone(), evaluation_cache: self.evaluation_cache.clone(), reported_trait_errors: self.reported_trait_errors.clone(), - reported_closure_mismatch: self.reported_closure_mismatch.clone(), + reported_signature_mismatch: self.reported_signature_mismatch.clone(), tainted_by_errors: self.tainted_by_errors.clone(), err_count_on_creation: self.err_count_on_creation, universe: self.universe.clone(), diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index fcc94687ed2..e164041c599 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -278,7 +278,7 @@ pub struct InferCtxt<'tcx> { /// avoid reporting the same error twice. pub reported_trait_errors: RefCell<FxIndexMap<Span, Vec<ty::Predicate<'tcx>>>>, - pub reported_closure_mismatch: RefCell<FxHashSet<(Span, Option<Span>)>>, + pub reported_signature_mismatch: RefCell<FxHashSet<(Span, Option<Span>)>>, /// When an error occurs, we want to avoid reporting "derived" /// errors that are due to this original failure. Normally, we @@ -702,7 +702,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> { selection_cache: Default::default(), evaluation_cache: Default::default(), reported_trait_errors: Default::default(), - reported_closure_mismatch: Default::default(), + reported_signature_mismatch: Default::default(), tainted_by_errors: Cell::new(None), err_count_on_creation: tcx.dcx().err_count(), universe: Cell::new(ty::UniverseIndex::ROOT), diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 03335996c03..32fba6ade88 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -202,8 +202,15 @@ pub(crate) fn parse_check_cfg(dcx: &DiagCtxt, specs: Vec<String>) -> CheckCfg { if !args.is_empty() { error!("`any()` must be empty"); } + } else if arg.has_name(sym::none) + && let Some(args) = arg.meta_item_list() + { + values.insert(None); + if !args.is_empty() { + error!("`none()` must be empty"); + } } else { - error!("`values()` arguments must be string literals or `any()`"); + error!("`values()` arguments must be string literals, `none()` or `any()`"); } } } else { diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 8d2f2aaca55..5e1f2ed11ac 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -1306,10 +1306,7 @@ impl<'tcx> LateLintPass<'tcx> for UngatedAsyncFnTrackCaller { cx.emit_spanned_lint( UNGATED_ASYNC_FN_TRACK_CALLER, attr.span, - BuiltinUngatedAsyncFnTrackCaller { - label: span, - parse_sess: &cx.tcx.sess.parse_sess, - }, + BuiltinUngatedAsyncFnTrackCaller { label: span, session: &cx.tcx.sess }, ); } } diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index 3c2d0c7b205..b98b1a2935c 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -786,7 +786,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { if let ast::LitKind::Str(rationale, _) = name_value.kind { if !self.features.lint_reasons { feature_err( - &self.sess.parse_sess, + &self.sess, sym::lint_reasons, item.span, "lint reasons are experimental", @@ -1074,7 +1074,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { lint.note(fluent::lint_note); rustc_session::parse::add_feature_diagnostics_for_issue( lint, - &self.sess.parse_sess, + &self.sess, feature, GateIssue::Language, lint_from_cli, diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index f370c4392b3..73db5790c2b 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -13,7 +13,7 @@ use rustc_macros::{LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::{ inhabitedness::InhabitedPredicate, Clause, PolyExistentialTraitRef, Ty, TyCtxt, }; -use rustc_session::parse::ParseSess; +use rustc_session::Session; use rustc_span::{edition::Edition, sym, symbol::Ident, Span, Symbol}; use crate::{ @@ -235,7 +235,7 @@ pub struct BuiltinUnstableFeatures; // lint_ungated_async_fn_track_caller pub struct BuiltinUngatedAsyncFnTrackCaller<'a> { pub label: Span, - pub parse_sess: &'a ParseSess, + pub session: &'a Session, } impl<'a> DecorateLint<'a, ()> for BuiltinUngatedAsyncFnTrackCaller<'_> { @@ -243,7 +243,7 @@ impl<'a> DecorateLint<'a, ()> for BuiltinUngatedAsyncFnTrackCaller<'_> { diag.span_label(self.label, fluent::lint_label); rustc_session::parse::add_feature_diagnostics( diag, - self.parse_sess, + self.session, sym::async_fn_track_caller, ); } diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index a639a887544..5e20a03bbc0 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -82,7 +82,7 @@ pub(crate) fn collect(tcx: TyCtxt<'_>, LocalCrate: LocalCrate) -> Vec<NativeLib> pub(crate) fn relevant_lib(sess: &Session, lib: &NativeLib) -> bool { match lib.cfg { - Some(ref cfg) => attr::cfg_matches(cfg, &sess.parse_sess, CRATE_NODE_ID, None), + Some(ref cfg) => attr::cfg_matches(cfg, sess, CRATE_NODE_ID, None), None => true, } } @@ -163,7 +163,7 @@ impl<'tcx> Collector<'tcx> { "link-arg" => { if !features.link_arg_attribute { feature_err( - &sess.parse_sess, + sess, sym::link_arg_attribute, span, "link kind `link-arg` is unstable", @@ -206,13 +206,8 @@ impl<'tcx> Collector<'tcx> { continue; }; if !features.link_cfg { - feature_err( - &sess.parse_sess, - sym::link_cfg, - item.span(), - "link cfg is unstable", - ) - .emit(); + feature_err(sess, sym::link_cfg, item.span(), "link cfg is unstable") + .emit(); } cfg = Some(link_cfg.clone()); } @@ -277,7 +272,7 @@ impl<'tcx> Collector<'tcx> { macro report_unstable_modifier($feature: ident) { if !features.$feature { feature_err( - &sess.parse_sess, + sess, sym::$feature, span, format!("linking modifier `{modifier}` is unstable"), @@ -520,11 +515,23 @@ impl<'tcx> Collector<'tcx> { ) -> DllImport { let span = self.tcx.def_span(item); + // this logic is similar to `Target::adjust_abi` (in rustc_target/src/spec/mod.rs) but errors on unsupported inputs let calling_convention = if self.tcx.sess.target.arch == "x86" { match abi { Abi::C { .. } | Abi::Cdecl { .. } => DllCallingConvention::C, - Abi::Stdcall { .. } | Abi::System { .. } => { - DllCallingConvention::Stdcall(self.i686_arg_list_size(item)) + Abi::Stdcall { .. } => DllCallingConvention::Stdcall(self.i686_arg_list_size(item)), + // On Windows, `extern "system"` behaves like msvc's `__stdcall`. + // `__stdcall` only applies on x86 and on non-variadic functions: + // https://learn.microsoft.com/en-us/cpp/cpp/stdcall?view=msvc-170 + Abi::System { .. } => { + let c_variadic = + self.tcx.type_of(item).instantiate_identity().fn_sig(self.tcx).c_variadic(); + + if c_variadic { + DllCallingConvention::C + } else { + DllCallingConvention::Stdcall(self.i686_arg_list_size(item)) + } } Abi::Fastcall { .. } => { DllCallingConvention::Fastcall(self.i686_arg_list_size(item)) diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs index 90b479cf2f4..efe7bdfa06d 100644 --- a/compiler/rustc_middle/src/middle/stability.rs +++ b/compiler/rustc_middle/src/middle/stability.rs @@ -116,8 +116,7 @@ pub fn report_unstable( if is_soft { soft_handler(SOFT_UNSTABLE, span, msg) } else { - let mut err = - feature_err_issue(&sess.parse_sess, feature, span, GateIssue::Library(issue), msg); + let mut err = feature_err_issue(sess, feature, span, GateIssue::Library(issue), msg); if let Some((inner_types, msg, sugg, applicability)) = suggestion { err.span_suggestion(inner_types, msg, sugg, applicability); } diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index af601a0d702..bebee8df10e 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -611,9 +611,6 @@ pub enum SelectionError<'tcx> { NotConstEvaluatable(NotConstEvaluatable), /// Exceeded the recursion depth during type projection. Overflow(OverflowError), - /// Signaling that an error has already been emitted, to avoid - /// multiple errors being shown. - ErrorReporting, /// Computing an opaque type's hidden type caused an error (e.g. a cycle error). /// We can thus not know whether the hidden type implements an auto trait, so /// we should not presume anything about it. diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs index 734c2b61c07..64f4af08e12 100644 --- a/compiler/rustc_middle/src/traits/select.rs +++ b/compiler/rustc_middle/src/traits/select.rs @@ -302,7 +302,6 @@ impl EvaluationResult { pub enum OverflowError { Error(ErrorGuaranteed), Canonical, - ErrorReporting, } impl From<ErrorGuaranteed> for OverflowError { @@ -318,7 +317,6 @@ impl<'tcx> From<OverflowError> for SelectionError<'tcx> { match overflow_error { OverflowError::Error(e) => SelectionError::Overflow(OverflowError::Error(e)), OverflowError::Canonical => SelectionError::Overflow(OverflowError::Canonical), - OverflowError::ErrorReporting => SelectionError::ErrorReporting, } } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 9e8d7c2ef3e..ad9296a4cc8 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<LintBuffer>, + + /// Information about functions signatures for delegation items expansion + pub has_self: LocalDefIdSet, + pub fn_parameter_counts: LocalDefIdMap<usize>, } #[derive(Clone, Copy, Debug)] diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index bcff820da79..3bd8ae02586 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<T>( &mut self, attrs: &mut AttrVec, diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index e4bbc9eeaf7..20ed2573e3a 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -1170,7 +1170,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { sym::rust_logo => { if !self.tcx.features().rustdoc_internals { feature_err( - &self.tcx.sess.parse_sess, + &self.tcx.sess, sym::rustdoc_internals, meta.span(), "the `#[doc(rust_logo)]` attribute is used for Rust branding", @@ -1815,7 +1815,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { (target, self.tcx.features().fn_align) { feature_err( - &self.tcx.sess.parse_sess, + &self.tcx.sess, sym::fn_align, hint.span(), "`repr(align)` attributes on functions are unstable", diff --git a/compiler/rustc_passes/src/check_const.rs b/compiler/rustc_passes/src/check_const.rs index 3e3f2771f5f..3676eb92a3f 100644 --- a/compiler/rustc_passes/src/check_const.rs +++ b/compiler/rustc_passes/src/check_const.rs @@ -147,7 +147,7 @@ impl<'tcx> CheckConstVisitor<'tcx> { [missing_primary, ref missing_secondary @ ..] => { let msg = format!("{} is not allowed in a `{}`", expr.name(), const_kind.keyword_name()); - let mut err = feature_err(&tcx.sess.parse_sess, *missing_primary, span, msg); + let mut err = feature_err(&tcx.sess, *missing_primary, span, msg); // If multiple feature gates would be required to enable this expression, include // them as help messages. Don't emit a separate error for each missing feature gate. diff --git a/compiler/rustc_passes/src/debugger_visualizer.rs b/compiler/rustc_passes/src/debugger_visualizer.rs index 42e929bde2c..4bfe6be5493 100644 --- a/compiler/rustc_passes/src/debugger_visualizer.rs +++ b/compiler/rustc_passes/src/debugger_visualizer.rs @@ -45,14 +45,13 @@ impl DebuggerVisualizerCollector<'_> { } }; - let file = - match resolve_path(&self.sess.parse_sess, visualizer_path.as_str(), attr.span) { - Ok(file) => file, - Err(err) => { - err.emit(); - return; - } - }; + let file = match resolve_path(&self.sess, visualizer_path.as_str(), attr.span) { + Ok(file) => file, + Err(err) => { + err.emit(); + return; + } + }; match std::fs::read(&file) { Ok(contents) => { diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs index ed26b45a936..a9d0e0d2dd3 100644 --- a/compiler/rustc_passes/src/entry.rs +++ b/compiler/rustc_passes/src/entry.rs @@ -135,7 +135,7 @@ fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) -> Option<(DefId, if main_def.is_import && !tcx.features().imported_main { let span = main_def.span; feature_err( - &tcx.sess.parse_sess, + &tcx.sess, sym::imported_main, span, "using an imported function as entry point `main` is experimental", diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs index c2392620cb2..ff29fc5929c 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 647f4d0e084..6aeaa8945fb 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 9ccfde5e3c6..a4e2f9e3ff8 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 02553d50071..b77102c085c 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/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 0d744238eeb..b5700661385 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -786,7 +786,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ResolutionError::SelfImportOnlyInImportListWithNonEmptyPrefix => { self.dcx().create_err(errs::SelfImportOnlyInImportListWithNonEmptyPrefix { span }) } - ResolutionError::FailedToResolve { last_segment, label, suggestion, module } => { + ResolutionError::FailedToResolve { segment, label, suggestion, module } => { let mut err = struct_span_code_err!(self.dcx(), span, E0433, "failed to resolve: {}", &label); err.span_label(span, label); @@ -801,9 +801,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if let Some(ModuleOrUniformRoot::Module(module)) = module && let Some(module) = module.opt_def_id() - && let Some(last_segment) = last_segment + && let Some(segment) = segment { - self.find_cfg_stripped(&mut err, &last_segment, module); + self.find_cfg_stripped(&mut err, &segment, module); } err @@ -981,12 +981,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } VisResolutionError::FailedToResolve(span, label, suggestion) => self.into_struct_error( span, - ResolutionError::FailedToResolve { - last_segment: None, - label, - suggestion, - module: None, - }, + ResolutionError::FailedToResolve { segment: None, label, suggestion, module: None }, ), VisResolutionError::ExpectedFound(span, path_str, res) => { self.dcx().create_err(errs::ExpectedFound { span, res, path_str }) @@ -2450,7 +2445,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { pub(crate) fn find_cfg_stripped( &mut self, err: &mut Diagnostic, - last_segment: &Symbol, + segment: &Symbol, module: DefId, ) { let local_items; @@ -2469,7 +2464,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { }; for &StrippedCfgItem { parent_module, name, ref cfg } in symbols { - if parent_module != module || name.name != *last_segment { + if parent_module != module || name.name != *segment { continue; } diff --git a/compiler/rustc_resolve/src/effective_visibilities.rs b/compiler/rustc_resolve/src/effective_visibilities.rs index 50352169221..3443bbe6e11 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/ident.rs b/compiler/rustc_resolve/src/ident.rs index 3a31addb109..7fb9db16e9c 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -1381,13 +1381,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { continue; } } - return PathResult::failed( - ident.span, - false, - finalize.is_some(), - module, - || ("there are too many leading `super` keywords".to_string(), None), - ); + return PathResult::failed(ident, false, finalize.is_some(), module, || { + ("there are too many leading `super` keywords".to_string(), None) + }); } if segment_idx == 0 { if name == kw::SelfLower { @@ -1419,7 +1415,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Report special messages for path segment keywords in wrong positions. if ident.is_path_segment_keyword() && segment_idx != 0 { - return PathResult::failed(ident.span, false, finalize.is_some(), module, || { + return PathResult::failed(ident, false, finalize.is_some(), module, || { let name_str = if name == kw::PathRoot { "crate root".to_string() } else { @@ -1515,7 +1511,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { )); } else { return PathResult::failed( - ident.span, + ident, is_last, finalize.is_some(), module, @@ -1541,24 +1537,18 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - return PathResult::failed( - ident.span, - is_last, - finalize.is_some(), - module, - || { - self.report_path_resolution_error( - path, - opt_ns, - parent_scope, - ribs, - ignore_binding, - module, - segment_idx, - ident, - ) - }, - ); + return PathResult::failed(ident, is_last, finalize.is_some(), module, || { + self.report_path_resolution_error( + path, + opt_ns, + parent_scope, + ribs, + ignore_binding, + module, + segment_idx, + ident, + ) + }); } } } diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 2ebf4c20562..f846dbec2c6 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -886,6 +886,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { PathResult::Failed { is_error_from_last_segment: false, span, + segment_name, label, suggestion, module, @@ -895,7 +896,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.report_error( span, ResolutionError::FailedToResolve { - last_segment: None, + segment: Some(segment_name), label, suggestion, module, diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 4a3c8dfe3d7..82f50227911 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 `<T as m::A>::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| { @@ -3998,11 +4054,12 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { label, suggestion, module, + segment_name, } => { return Err(respan( span, ResolutionError::FailedToResolve { - last_segment: None, + segment: Some(segment_name), label, suggestion, module, @@ -4551,13 +4608,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 +4637,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 +4658,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 2f476ae6cbc..58ff4d8c793 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 a14f3d494fb..90aa7d79bf0 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -213,7 +213,7 @@ enum ResolutionError<'a> { SelfImportOnlyInImportListWithNonEmptyPrefix, /// Error E0433: failed to resolve. FailedToResolve { - last_segment: Option<Symbol>, + segment: Option<Symbol>, label: String, suggestion: Option<Suggestion>, module: Option<ModuleOrUniformRoot<'a>>, @@ -396,12 +396,14 @@ enum PathResult<'a> { suggestion: Option<Suggestion>, is_error_from_last_segment: bool, module: Option<ModuleOrUniformRoot<'a>>, + /// The segment name of target + segment_name: Symbol, }, } impl<'a> PathResult<'a> { fn failed( - span: Span, + ident: Ident, is_error_from_last_segment: bool, finalize: bool, module: Option<ModuleOrUniformRoot<'a>>, @@ -409,7 +411,14 @@ impl<'a> PathResult<'a> { ) -> PathResult<'a> { let (label, suggestion) = if finalize { label_and_suggestion() } else { (String::new(), None) }; - PathResult::Failed { span, label, suggestion, is_error_from_last_segment, module } + PathResult::Failed { + span: ident.span, + segment_name: ident.name, + label, + suggestion, + is_error_from_last_segment, + module, + } } } @@ -1101,6 +1110,8 @@ pub struct Resolver<'a, 'tcx> { legacy_const_generic_args: FxHashMap<DefId, Option<Vec<usize>>>, /// Amount of lifetime parameters for each item in the crate. item_generics_num_lifetimes: FxHashMap<LocalDefId, usize>, + /// Amount of parameters for each function in the crate. + fn_parameter_counts: LocalDefIdMap<usize>, main_def: Option<MainDefinition>, trait_impls: FxIndexMap<DefId, Vec<LocalDefId>>, @@ -1439,6 +1450,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 +1554,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_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 66ecaeb4449..1c085ddf57b 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -594,13 +594,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if soft_custom_inner_attributes_gate { self.tcx.sess.parse_sess.buffer_lint(SOFT_UNSTABLE, path.span, node_id, msg); } else { - feature_err( - &self.tcx.sess.parse_sess, - sym::custom_inner_attributes, - path.span, - msg, - ) - .emit(); + feature_err(&self.tcx.sess, sym::custom_inner_attributes, path.span, msg).emit(); } } @@ -779,7 +773,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.report_error( span, ResolutionError::FailedToResolve { - last_segment: path.last().map(|segment| segment.ident.name), + segment: path.last().map(|segment| segment.ident.name), label, suggestion, module, diff --git a/compiler/rustc_session/messages.ftl b/compiler/rustc_session/messages.ftl index f2e646c70f5..53bdef6dfa0 100644 --- a/compiler/rustc_session/messages.ftl +++ b/compiler/rustc_session/messages.ftl @@ -24,6 +24,9 @@ session_feature_diagnostic_for_issue = session_feature_diagnostic_help = add `#![feature({$feature})]` to the crate attributes to enable +session_feature_suggest_upgrade_compiler = + this compiler was built on {$date}; consider upgrading it if it is out of date + session_file_is_not_writeable = output file {$file} is not writeable -- check its permissions session_file_write_fail = failed to write `{$path}` due to error `{$err}` diff --git a/compiler/rustc_session/src/config/sigpipe.rs b/compiler/rustc_session/src/config/sigpipe.rs index 53692ad7cc9..1fadc75cfd0 100644 --- a/compiler/rustc_session/src/config/sigpipe.rs +++ b/compiler/rustc_session/src/config/sigpipe.rs @@ -1,7 +1,7 @@ -//! NOTE: Keep these constants in sync with `library/std/src/sys/unix/mod.rs`! +//! NOTE: Keep these constants in sync with `library/std/src/sys/pal/unix/mod.rs`! /// The default value if `#[unix_sigpipe]` is not specified. This resolves -/// to `SIG_IGN` in `library/std/src/sys/unix/mod.rs`. +/// to `SIG_IGN` in `library/std/src/sys/pal/unix/mod.rs`. /// /// Note that `SIG_IGN` has been the Rust default since 2014. See /// <https://github.com/rust-lang/rust/issues/62569>. diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index b672e760feb..21a206798af 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -1,6 +1,5 @@ use std::num::NonZeroU32; -use crate::parse::ParseSess; use rustc_ast::token; use rustc_ast::util::literal::LitError; use rustc_errors::{ @@ -10,6 +9,8 @@ use rustc_macros::Diagnostic; use rustc_span::{BytePos, Span, Symbol}; use rustc_target::spec::{SplitDebuginfo, StackProtector, TargetTriple}; +use crate::parse::ParseSess; + pub struct FeatureGateError { pub span: MultiSpan, pub explain: DiagnosticMessage, @@ -31,6 +32,24 @@ pub struct FeatureDiagnosticForIssue { } #[derive(Subdiagnostic)] +#[note(session_feature_suggest_upgrade_compiler)] +pub struct SuggestUpgradeCompiler { + date: &'static str, +} + +impl SuggestUpgradeCompiler { + pub fn ui_testing() -> Self { + Self { date: "YYYY-MM-DD" } + } + + pub fn new() -> Option<Self> { + let date = option_env!("CFG_VER_DATE")?; + + Some(Self { date }) + } +} + +#[derive(Subdiagnostic)] #[help(session_feature_diagnostic_help)] pub struct FeatureDiagnosticHelp { pub feature: Symbol, diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index 598178c3c2a..c629c9884c8 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -4,10 +4,12 @@ use crate::config::{Cfg, CheckCfg}; use crate::errors::{ CliFeatureDiagnosticHelp, FeatureDiagnosticForIssue, FeatureDiagnosticHelp, FeatureGateError, + SuggestUpgradeCompiler, }; use crate::lint::{ builtin::UNSTABLE_SYNTAX_PRE_EXPANSION, BufferedEarlyLint, BuiltinLintDiagnostics, Lint, LintId, }; +use crate::Session; use rustc_ast::node_id::NodeId; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::{AppendOnlyVec, Lock, Lrc}; @@ -75,11 +77,12 @@ impl SymbolGallery { } } +// todo: this function now accepts `Session` instead of `ParseSess` and should be relocated /// Construct a diagnostic for a language feature error due to the given `span`. /// The `feature`'s `Symbol` is the one you used in `unstable.rs` and `rustc_span::symbols`. #[track_caller] pub fn feature_err( - sess: &ParseSess, + sess: &Session, feature: Symbol, span: impl Into<MultiSpan>, explain: impl Into<DiagnosticMessage>, @@ -93,7 +96,7 @@ pub fn feature_err( /// Almost always, you want to use this for a language feature. If so, prefer `feature_err`. #[track_caller] pub fn feature_err_issue( - sess: &ParseSess, + sess: &Session, feature: Symbol, span: impl Into<MultiSpan>, issue: GateIssue, @@ -103,12 +106,14 @@ pub fn feature_err_issue( // Cancel an earlier warning for this same error, if it exists. if let Some(span) = span.primary_span() { - if let Some(err) = sess.dcx.steal_diagnostic(span, StashKey::EarlySyntaxWarning) { + if let Some(err) = sess.parse_sess.dcx.steal_diagnostic(span, StashKey::EarlySyntaxWarning) + { err.cancel() } } - let mut err = sess.dcx.create_err(FeatureGateError { span, explain: explain.into() }); + let mut err = + sess.parse_sess.dcx.create_err(FeatureGateError { span, explain: explain.into() }); add_feature_diagnostics_for_issue(&mut err, sess, feature, issue, false); err } @@ -117,7 +122,7 @@ pub fn feature_err_issue( /// /// This diagnostic is only a warning and *does not cause compilation to fail*. #[track_caller] -pub fn feature_warn(sess: &ParseSess, feature: Symbol, span: Span, explain: &'static str) { +pub fn feature_warn(sess: &Session, feature: Symbol, span: Span, explain: &'static str) { feature_warn_issue(sess, feature, span, GateIssue::Language, explain); } @@ -131,13 +136,13 @@ pub fn feature_warn(sess: &ParseSess, feature: Symbol, span: Span, explain: &'st #[allow(rustc::untranslatable_diagnostic)] #[track_caller] pub fn feature_warn_issue( - sess: &ParseSess, + sess: &Session, feature: Symbol, span: Span, issue: GateIssue, explain: &'static str, ) { - let mut err = sess.dcx.struct_span_warn(span, explain); + let mut err = sess.parse_sess.dcx.struct_span_warn(span, explain); add_feature_diagnostics_for_issue(&mut err, sess, feature, issue, false); // Decorate this as a future-incompatibility lint as in rustc_middle::lint::struct_lint_level @@ -152,7 +157,7 @@ pub fn feature_warn_issue( } /// Adds the diagnostics for a feature to an existing error. -pub fn add_feature_diagnostics(err: &mut Diagnostic, sess: &ParseSess, feature: Symbol) { +pub fn add_feature_diagnostics(err: &mut Diagnostic, sess: &Session, feature: Symbol) { add_feature_diagnostics_for_issue(err, sess, feature, GateIssue::Language, false); } @@ -163,7 +168,7 @@ pub fn add_feature_diagnostics(err: &mut Diagnostic, sess: &ParseSess, feature: /// `add_feature_diagnostics`. pub fn add_feature_diagnostics_for_issue( err: &mut Diagnostic, - sess: &ParseSess, + sess: &Session, feature: Symbol, issue: GateIssue, feature_from_cli: bool, @@ -173,12 +178,18 @@ pub fn add_feature_diagnostics_for_issue( } // #23973: do not suggest `#![feature(...)]` if we are in beta/stable - if sess.unstable_features.is_nightly_build() { + if sess.parse_sess.unstable_features.is_nightly_build() { if feature_from_cli { err.subdiagnostic(CliFeatureDiagnosticHelp { feature }); } else { err.subdiagnostic(FeatureDiagnosticHelp { feature }); } + + if sess.opts.unstable_opts.ui_testing { + err.subdiagnostic(SuggestUpgradeCompiler::ui_testing()); + } else if let Some(suggestion) = SuggestUpgradeCompiler::new() { + err.subdiagnostic(suggestion); + } } } diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 210dc9e0145..1c3d5a3cb88 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -318,7 +318,7 @@ impl Session { if err.code.is_none() { err.code(error_code!(E0658)); } - add_feature_diagnostics(&mut err, &self.parse_sess, feature); + add_feature_diagnostics(&mut err, self, feature); err } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 8ed1255c010..72b62a795fc 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/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs index fafc10e7163..1c83039047e 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/abi/call/mod.rs @@ -840,7 +840,7 @@ impl<'a, Ty> FnAbi<'a, Ty> { "sparc" => sparc::compute_abi_info(cx, self), "sparc64" => sparc64::compute_abi_info(cx, self), "nvptx64" => { - if cx.target_spec().adjust_abi(abi) == spec::abi::Abi::PtxKernel { + if cx.target_spec().adjust_abi(abi, self.c_variadic) == spec::abi::Abi::PtxKernel { nvptx64::compute_ptx_kernel_abi_info(cx, self) } else { nvptx64::compute_abi_info(self) @@ -849,7 +849,7 @@ impl<'a, Ty> FnAbi<'a, Ty> { "hexagon" => hexagon::compute_abi_info(self), "riscv32" | "riscv64" => riscv::compute_abi_info(cx, self), "wasm32" | "wasm64" => { - if cx.target_spec().adjust_abi(abi) == spec::abi::Abi::Wasm { + if cx.target_spec().adjust_abi(abi, self.c_variadic) == spec::abi::Abi::Wasm { wasm::compute_wasm_abi_info(self) } else { wasm::compute_c_abi_info(cx, self) diff --git a/compiler/rustc_target/src/spec/abi/mod.rs b/compiler/rustc_target/src/spec/abi/mod.rs index 4c1f0c01a04..1a0aa6f0c4a 100644 --- a/compiler/rustc_target/src/spec/abi/mod.rs +++ b/compiler/rustc_target/src/spec/abi/mod.rs @@ -70,15 +70,16 @@ impl Abi { // * C and Cdecl obviously support varargs. // * C can be based on Aapcs, SysV64 or Win64, so they must support varargs. // * EfiApi is based on Win64 or C, so it also supports it. + // * System falls back to C for functions with varargs. // // * Stdcall does not, because it would be impossible for the callee to clean // up the arguments. (callee doesn't know how many arguments are there) // * Same for Fastcall, Vectorcall and Thiscall. - // * System can become Stdcall, so is also a no-no. // * Other calling conventions are related to hardware or the compiler itself. match self { Self::C { .. } | Self::Cdecl { .. } + | Self::System { .. } | Self::Aapcs { .. } | Self::Win64 { .. } | Self::SysV64 { .. } diff --git a/compiler/rustc_target/src/spec/base/illumos.rs b/compiler/rustc_target/src/spec/base/illumos.rs index e63e789752b..f0a648b93ad 100644 --- a/compiler/rustc_target/src/spec/base/illumos.rs +++ b/compiler/rustc_target/src/spec/base/illumos.rs @@ -39,7 +39,7 @@ pub fn opts() -> TargetOptions { // While we support ELF TLS, rust requires a way to register // cleanup handlers (in C, this would be something along the lines of: // void register_callback(void (*fn)(void *), void *arg); - // (see src/libstd/sys/unix/fast_thread_local.rs) that is currently + // (see src/libstd/sys/pal/unix/fast_thread_local.rs) that is currently // missing in illumos. For now at least, we must fallback to using // pthread_{get,set}specific. //has_thread_local: true, diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index da8706ea715..5d74ebebdf3 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -2401,10 +2401,14 @@ impl DerefMut for Target { impl Target { /// Given a function ABI, turn it into the correct ABI for this target. - pub fn adjust_abi(&self, abi: Abi) -> Abi { + pub fn adjust_abi(&self, abi: Abi, c_variadic: bool) -> Abi { match abi { Abi::C { .. } => self.default_adjusted_cabi.unwrap_or(abi), - Abi::System { unwind } if self.is_like_windows && self.arch == "x86" => { + + // On Windows, `extern "system"` behaves like msvc's `__stdcall`. + // `__stdcall` only applies on x86 and on non-variadic functions: + // https://learn.microsoft.com/en-us/cpp/cpp/stdcall?view=msvc-170 + Abi::System { unwind } if self.is_like_windows && self.arch == "x86" && !c_variadic => { Abi::Stdcall { unwind } } Abi::System { unwind } => Abi::C { unwind }, diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs index 100c9a70aaa..532e2cb36e3 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs @@ -408,7 +408,7 @@ impl<'tcx> OnUnimplementedDirective { .ok_or_else(|| tcx.dcx().emit_err(EmptyOnClauseInOnUnimplemented { span }))? .meta_item() .ok_or_else(|| tcx.dcx().emit_err(InvalidOnClauseInOnUnimplemented { span }))?; - attr::eval_condition(cond, &tcx.sess.parse_sess, Some(tcx.features()), &mut |cfg| { + attr::eval_condition(cond, &tcx.sess, Some(tcx.features()), &mut |cfg| { if let Some(value) = cfg.value && let Err(guar) = parse_value(value, cfg.span) { @@ -682,31 +682,22 @@ impl<'tcx> OnUnimplementedDirective { for command in self.subcommands.iter().chain(Some(self)).rev() { if let Some(ref condition) = command.condition - && !attr::eval_condition( - condition, - &tcx.sess.parse_sess, - Some(tcx.features()), - &mut |cfg| { - let value = cfg.value.map(|v| { - // `with_no_visible_paths` is also used when generating the options, - // so we need to match it here. - ty::print::with_no_visible_paths!( - OnUnimplementedFormatString { - symbol: v, - span: cfg.span, - is_diagnostic_namespace_variant: false - } - .format( - tcx, - trait_ref, - &options_map - ) - ) - }); - - options.contains(&(cfg.name, value)) - }, - ) + && !attr::eval_condition(condition, &tcx.sess, Some(tcx.features()), &mut |cfg| { + let value = cfg.value.map(|v| { + // `with_no_visible_paths` is also used when generating the options, + // so we need to match it here. + ty::print::with_no_visible_paths!( + OnUnimplementedFormatString { + symbol: v, + span: cfg.span, + is_diagnostic_namespace_variant: false + } + .format(tcx, trait_ref, &options_map) + ) + }); + + options.contains(&(cfg.name, value)) + }) { debug!("evaluate: skipping {:?} due to condition", command); continue; diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index 47a700805fa..b970ec7f726 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -947,9 +947,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { Overflow(_) => { bug!("overflow should be handled before the `report_selection_error` path"); } - SelectionError::ErrorReporting => { - bug!("ErrorReporting Overflow should not reach `report_selection_err` call") - } }; self.note_obligation_cause(&mut err, &obligation); @@ -3459,14 +3456,12 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let found_node = found_did.and_then(|did| self.tcx.hir().get_if_local(did)); let found_span = found_did.and_then(|did| self.tcx.hir().span_if_local(did)); - if self.reported_closure_mismatch.borrow().contains(&(span, found_span)) { + if !self.reported_signature_mismatch.borrow_mut().insert((span, found_span)) { // We check closures twice, with obligations flowing in different directions, // but we want to complain about them only once. return None; } - self.reported_closure_mismatch.borrow_mut().insert((span, found_span)); - let mut not_tupled = false; let found = match found_trait_ref.skip_binder().args.type_at(1).kind() { diff --git a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs index 31e34096fb0..4c0c57377e0 100644 --- a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs +++ b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs @@ -116,11 +116,9 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { r, ) } - OverflowError::ErrorReporting => EvaluationResult::EvaluatedToErr, OverflowError::Error(_) => EvaluationResult::EvaluatedToErr, }) } - Err(OverflowError::ErrorReporting) => EvaluationResult::EvaluatedToErr, Err(OverflowError::Error(_)) => EvaluationResult::EvaluatedToErr, } } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 61fe2c8efe3..6a6adcbb680 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -14,9 +14,9 @@ use super::util; use super::util::closure_trait_ref_and_return_type; use super::wf; use super::{ - ErrorReporting, ImplDerivedObligation, ImplDerivedObligationCause, Normalized, Obligation, - ObligationCause, ObligationCauseCode, Overflow, PolyTraitObligation, PredicateObligation, - Selection, SelectionError, SelectionResult, TraitQueryMode, + ImplDerivedObligation, ImplDerivedObligationCause, Normalized, Obligation, ObligationCause, + ObligationCauseCode, Overflow, PolyTraitObligation, PredicateObligation, Selection, + SelectionError, SelectionResult, TraitQueryMode, }; use crate::infer::{InferCtxt, InferOk, TypeFreshener}; @@ -496,7 +496,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } Ok(_) => Ok(None), Err(OverflowError::Canonical) => Err(Overflow(OverflowError::Canonical)), - Err(OverflowError::ErrorReporting) => Err(ErrorReporting), Err(OverflowError::Error(e)) => Err(Overflow(OverflowError::Error(e))), }) .flat_map(Result::transpose) @@ -1233,7 +1232,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Ok(Some(c)) => self.evaluate_candidate(stack, &c), Ok(None) => Ok(EvaluatedToAmbig), Err(Overflow(OverflowError::Canonical)) => Err(OverflowError::Canonical), - Err(ErrorReporting) => Err(OverflowError::ErrorReporting), Err(..) => Ok(EvaluatedToErr), } } diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index 2772831e731..6e8293dac31 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -228,9 +228,9 @@ fn fn_sig_for_fn_abi<'tcx>( } #[inline] -fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: SpecAbi) -> Conv { +fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: SpecAbi, c_variadic: bool) -> Conv { use rustc_target::spec::abi::Abi::*; - match tcx.sess.target.adjust_abi(abi) { + match tcx.sess.target.adjust_abi(abi, c_variadic) { RustIntrinsic | PlatformIntrinsic | Rust | RustCall => Conv::Rust, // This is intentionally not using `Conv::Cold`, as that has to preserve @@ -488,7 +488,7 @@ fn fn_abi_new_uncached<'tcx>( ) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, &'tcx FnAbiError<'tcx>> { let sig = cx.tcx.normalize_erasing_late_bound_regions(cx.param_env, sig); - let conv = conv_from_spec_abi(cx.tcx(), sig.abi); + let conv = conv_from_spec_abi(cx.tcx(), sig.abi, sig.c_variadic); let mut inputs = sig.inputs(); let extra_args = if sig.abi == RustCall { |
