diff options
Diffstat (limited to 'compiler/rustc_ast_lowering')
-rw-r--r-- | compiler/rustc_ast_lowering/Cargo.toml | 14 | ||||
-rw-r--r-- | compiler/rustc_ast_lowering/src/asm.rs | 191 | ||||
-rw-r--r-- | compiler/rustc_ast_lowering/src/block.rs | 13 | ||||
-rw-r--r-- | compiler/rustc_ast_lowering/src/errors.rs | 347 | ||||
-rw-r--r-- | compiler/rustc_ast_lowering/src/expr.rs | 235 | ||||
-rw-r--r-- | compiler/rustc_ast_lowering/src/index.rs | 45 | ||||
-rw-r--r-- | compiler/rustc_ast_lowering/src/item.rs | 162 | ||||
-rw-r--r-- | compiler/rustc_ast_lowering/src/lib.rs | 479 | ||||
-rw-r--r-- | compiler/rustc_ast_lowering/src/lifetime_collector.rs | 15 | ||||
-rw-r--r-- | compiler/rustc_ast_lowering/src/pat.rs | 112 | ||||
-rw-r--r-- | compiler/rustc_ast_lowering/src/path.rs | 46 |
11 files changed, 1009 insertions, 650 deletions
diff --git a/compiler/rustc_ast_lowering/Cargo.toml b/compiler/rustc_ast_lowering/Cargo.toml index 39ba62ef2..ce1c8d499 100644 --- a/compiler/rustc_ast_lowering/Cargo.toml +++ b/compiler/rustc_ast_lowering/Cargo.toml @@ -8,16 +8,18 @@ doctest = false [dependencies] rustc_arena = { path = "../rustc_arena" } -tracing = "0.1" +rustc_ast = { path = "../rustc_ast" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } -rustc_hir = { path = "../rustc_hir" } -rustc_target = { path = "../rustc_target" } rustc_data_structures = { path = "../rustc_data_structures" } +rustc_errors = { path = "../rustc_errors" } +rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } rustc_middle = { path = "../rustc_middle" } +rustc_macros = { path = "../rustc_macros" } rustc_query_system = { path = "../rustc_query_system" } -rustc_span = { path = "../rustc_span" } -rustc_errors = { path = "../rustc_errors" } rustc_session = { path = "../rustc_session" } -rustc_ast = { path = "../rustc_ast" } +rustc_span = { path = "../rustc_span" } +rustc_target = { path = "../rustc_target" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } +thin-vec = "0.2.8" +tracing = "0.1" diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index 4166b4fc2..24672efc6 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -1,11 +1,17 @@ use crate::{ImplTraitContext, ImplTraitPosition, ParamMode, ResolverAstLoweringExt}; +use super::errors::{ + AbiSpecifiedMultipleTimes, AttSyntaxOnlyX86, ClobberAbiNotSupported, + InlineAsmUnsupportedTarget, InvalidAbiClobberAbi, InvalidAsmTemplateModifierConst, + InvalidAsmTemplateModifierRegClass, InvalidAsmTemplateModifierRegClassSub, + InvalidAsmTemplateModifierSym, InvalidRegister, InvalidRegisterClass, RegisterClassOnlyClobber, + RegisterConflict, +}; use super::LoweringContext; use rustc_ast::ptr::P; use rustc_ast::*; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::definitions::DefPathData; @@ -26,13 +32,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let asm_arch = if self.tcx.sess.opts.actually_rustdoc { None } else { self.tcx.sess.asm_arch }; if asm_arch.is_none() && !self.tcx.sess.opts.actually_rustdoc { - struct_span_err!( - self.tcx.sess, - sp, - E0472, - "inline assembly is unsupported on this target" - ) - .emit(); + self.tcx.sess.emit_err(InlineAsmUnsupportedTarget { span: sp }); } if let Some(asm_arch) = asm_arch { // Inline assembly is currently only stable for these architectures. @@ -59,10 +59,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { && !matches!(asm_arch, Some(asm::InlineAsmArch::X86 | asm::InlineAsmArch::X86_64)) && !self.tcx.sess.opts.actually_rustdoc { - self.tcx - .sess - .struct_span_err(sp, "the `att_syntax` option is only supported on x86") - .emit(); + self.tcx.sess.emit_err(AttSyntaxOnlyX86 { span: sp }); } if asm.options.contains(InlineAsmOptions::MAY_UNWIND) && !self.tcx.features().asm_unwind { feature_err( @@ -82,51 +79,37 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // If the abi was already in the list, emit an error match clobber_abis.get(&abi) { Some((prev_name, prev_sp)) => { - let mut err = self.tcx.sess.struct_span_err( - *abi_span, - &format!("`{}` ABI specified multiple times", prev_name), - ); - err.span_label(*prev_sp, "previously specified here"); - // Multiple different abi names may actually be the same ABI // If the specified ABIs are not the same name, alert the user that they resolve to the same ABI let source_map = self.tcx.sess.source_map(); - if source_map.span_to_snippet(*prev_sp) - != source_map.span_to_snippet(*abi_span) - { - err.note("these ABIs are equivalent on the current target"); - } + let equivalent = (source_map.span_to_snippet(*prev_sp) + != source_map.span_to_snippet(*abi_span)) + .then_some(()); - err.emit(); + self.tcx.sess.emit_err(AbiSpecifiedMultipleTimes { + abi_span: *abi_span, + prev_name: *prev_name, + prev_span: *prev_sp, + equivalent, + }); } None => { - clobber_abis.insert(abi, (abi_name, *abi_span)); + clobber_abis.insert(abi, (*abi_name, *abi_span)); } } } Err(&[]) => { - self.tcx - .sess - .struct_span_err( - *abi_span, - "`clobber_abi` is not supported on this target", - ) - .emit(); + self.tcx.sess.emit_err(ClobberAbiNotSupported { abi_span: *abi_span }); } Err(supported_abis) => { - let mut err = self - .tcx - .sess - .struct_span_err(*abi_span, "invalid ABI for `clobber_abi`"); let mut abis = format!("`{}`", supported_abis[0]); for m in &supported_abis[1..] { let _ = write!(abis, ", `{}`", m); } - err.note(&format!( - "the following ABIs are supported on this target: {}", - abis - )); - err.emit(); + self.tcx.sess.emit_err(InvalidAbiClobberAbi { + abi_span: *abi_span, + supported_abis: abis, + }); } } } @@ -141,24 +124,28 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { .iter() .map(|(op, op_sp)| { let lower_reg = |reg| match reg { - InlineAsmRegOrRegClass::Reg(s) => { + InlineAsmRegOrRegClass::Reg(reg) => { asm::InlineAsmRegOrRegClass::Reg(if let Some(asm_arch) = asm_arch { - asm::InlineAsmReg::parse(asm_arch, s).unwrap_or_else(|e| { - let msg = format!("invalid register `{}`: {}", s, e); - sess.struct_span_err(*op_sp, &msg).emit(); + asm::InlineAsmReg::parse(asm_arch, reg).unwrap_or_else(|error| { + sess.emit_err(InvalidRegister { op_span: *op_sp, reg, error }); asm::InlineAsmReg::Err }) } else { asm::InlineAsmReg::Err }) } - InlineAsmRegOrRegClass::RegClass(s) => { + InlineAsmRegOrRegClass::RegClass(reg_class) => { asm::InlineAsmRegOrRegClass::RegClass(if let Some(asm_arch) = asm_arch { - asm::InlineAsmRegClass::parse(asm_arch, s).unwrap_or_else(|e| { - let msg = format!("invalid register class `{}`: {}", s, e); - sess.struct_span_err(*op_sp, &msg).emit(); - asm::InlineAsmRegClass::Err - }) + asm::InlineAsmRegClass::parse(asm_arch, reg_class).unwrap_or_else( + |error| { + sess.emit_err(InvalidRegisterClass { + op_span: *op_sp, + reg_class, + error, + }); + asm::InlineAsmRegClass::Err + }, + ) } else { asm::InlineAsmRegClass::Err }) @@ -168,26 +155,26 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let op = match *op { InlineAsmOperand::In { reg, ref expr } => hir::InlineAsmOperand::In { reg: lower_reg(reg), - expr: self.lower_expr_mut(expr), + expr: self.lower_expr(expr), }, InlineAsmOperand::Out { reg, late, ref expr } => hir::InlineAsmOperand::Out { reg: lower_reg(reg), late, - expr: expr.as_ref().map(|expr| self.lower_expr_mut(expr)), + expr: expr.as_ref().map(|expr| self.lower_expr(expr)), }, InlineAsmOperand::InOut { reg, late, ref expr } => { hir::InlineAsmOperand::InOut { reg: lower_reg(reg), late, - expr: self.lower_expr_mut(expr), + expr: self.lower_expr(expr), } } InlineAsmOperand::SplitInOut { reg, late, ref in_expr, ref out_expr } => { hir::InlineAsmOperand::SplitInOut { reg: lower_reg(reg), late, - in_expr: self.lower_expr_mut(in_expr), - out_expr: out_expr.as_ref().map(|expr| self.lower_expr_mut(expr)), + in_expr: self.lower_expr(in_expr), + out_expr: out_expr.as_ref().map(|expr| self.lower_expr(expr)), } } InlineAsmOperand::Const { ref anon_const } => { @@ -233,7 +220,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &sym.qself, &sym.path, ParamMode::Optional, - ImplTraitContext::Disallowed(ImplTraitPosition::Path), + &ImplTraitContext::Disallowed(ImplTraitPosition::Path), ); hir::InlineAsmOperand::SymStatic { path, def_id } } else { @@ -282,50 +269,39 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } let valid_modifiers = class.valid_modifiers(asm_arch.unwrap()); if !valid_modifiers.contains(&modifier) { - let mut err = sess.struct_span_err( - placeholder_span, - "invalid asm template modifier for this register class", - ); - err.span_label(placeholder_span, "template modifier"); - err.span_label(op_sp, "argument"); - if !valid_modifiers.is_empty() { + let sub = if !valid_modifiers.is_empty() { let mut mods = format!("`{}`", valid_modifiers[0]); for m in &valid_modifiers[1..] { let _ = write!(mods, ", `{}`", m); } - err.note(&format!( - "the `{}` register class supports \ - the following template modifiers: {}", - class.name(), - mods - )); + InvalidAsmTemplateModifierRegClassSub::SupportModifier { + class_name: class.name(), + modifiers: mods, + } } else { - err.note(&format!( - "the `{}` register class does not support template modifiers", - class.name() - )); - } - err.emit(); + InvalidAsmTemplateModifierRegClassSub::DoesNotSupportModifier { + class_name: class.name(), + } + }; + sess.emit_err(InvalidAsmTemplateModifierRegClass { + placeholder_span, + op_span: op_sp, + sub, + }); } } hir::InlineAsmOperand::Const { .. } => { - let mut err = sess.struct_span_err( + sess.emit_err(InvalidAsmTemplateModifierConst { placeholder_span, - "asm template modifiers are not allowed for `const` arguments", - ); - err.span_label(placeholder_span, "template modifier"); - err.span_label(op_sp, "argument"); - err.emit(); + op_span: op_sp, + }); } hir::InlineAsmOperand::SymFn { .. } | hir::InlineAsmOperand::SymStatic { .. } => { - let mut err = sess.struct_span_err( + sess.emit_err(InvalidAsmTemplateModifierSym { placeholder_span, - "asm template modifiers are not allowed for `sym` arguments", - ); - err.span_label(placeholder_span, "template modifier"); - err.span_label(op_sp, "argument"); - err.emit(); + op_span: op_sp, + }); } } } @@ -346,12 +322,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // require that the operand name an explicit register, not a // register class. if reg_class.is_clobber_only(asm_arch.unwrap()) && !op.is_clobber() { - let msg = format!( - "register class `{}` can only be used as a clobber, \ - not as an input or output", - reg_class.name() - ); - sess.struct_span_err(op_sp, &msg).emit(); + sess.emit_err(RegisterClassOnlyClobber { + op_span: op_sp, + reg_class_name: reg_class.name(), + }); continue; } @@ -391,16 +365,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { unreachable!(); }; - let msg = format!( - "register `{}` conflicts with register `{}`", - reg.name(), - reg2.name() - ); - let mut err = sess.struct_span_err(op_sp, &msg); - err.span_label(op_sp, &format!("register `{}`", reg.name())); - err.span_label(op_sp2, &format!("register `{}`", reg2.name())); - - match (op, op2) { + let in_out = match (op, op2) { ( hir::InlineAsmOperand::In { .. }, hir::InlineAsmOperand::Out { late, .. }, @@ -411,14 +376,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ) => { assert!(!*late); let out_op_sp = if input { op_sp2 } else { op_sp }; - let msg = "use `lateout` instead of \ - `out` to avoid conflict"; - err.span_help(out_op_sp, msg); - } - _ => {} - } + Some(out_op_sp) + }, + _ => None, + }; - err.emit(); + sess.emit_err(RegisterConflict { + op_span1: op_sp, + op_span2: op_sp2, + reg1_name: reg.name(), + reg2_name: reg2.name(), + in_out + }); } Entry::Vacant(v) => { if r == reg { diff --git a/compiler/rustc_ast_lowering/src/block.rs b/compiler/rustc_ast_lowering/src/block.rs index 7cbfe143b..12a0cc0d2 100644 --- a/compiler/rustc_ast_lowering/src/block.rs +++ b/compiler/rustc_ast_lowering/src/block.rs @@ -1,8 +1,6 @@ use crate::{ImplTraitContext, ImplTraitPosition, LoweringContext}; use rustc_ast::{Block, BlockCheckMode, Local, LocalKind, Stmt, StmtKind}; use rustc_hir as hir; -use rustc_session::parse::feature_err; -use rustc_span::sym; use smallvec::SmallVec; @@ -87,20 +85,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let ty = l .ty .as_ref() - .map(|t| self.lower_ty(t, ImplTraitContext::Disallowed(ImplTraitPosition::Variable))); + .map(|t| self.lower_ty(t, &ImplTraitContext::Disallowed(ImplTraitPosition::Variable))); let init = l.kind.init().map(|init| self.lower_expr(init)); let hir_id = self.lower_node_id(l.id); let pat = self.lower_pat(&l.pat); let els = if let LocalKind::InitElse(_, els) = &l.kind { - if !self.tcx.features().let_else { - feature_err( - &self.tcx.sess.parse_sess, - sym::let_else, - l.span, - "`let...else` statements are unstable", - ) - .emit(); - } Some(self.lower_block(els, false)) } else { None diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs new file mode 100644 index 000000000..c87d0ca96 --- /dev/null +++ b/compiler/rustc_ast_lowering/src/errors.rs @@ -0,0 +1,347 @@ +use rustc_errors::{fluent, AddSubdiagnostic, Applicability, Diagnostic, DiagnosticArgFromDisplay}; +use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic}; +use rustc_span::{symbol::Ident, Span, Symbol}; + +#[derive(SessionDiagnostic, Clone, Copy)] +#[diag(ast_lowering::generic_type_with_parentheses, code = "E0214")] +pub struct GenericTypeWithParentheses { + #[primary_span] + #[label] + pub span: Span, + #[subdiagnostic] + pub sub: Option<UseAngleBrackets>, +} + +#[derive(Clone, Copy)] +pub struct UseAngleBrackets { + pub open_param: Span, + pub close_param: Span, +} + +impl AddSubdiagnostic for UseAngleBrackets { + fn add_to_diagnostic(self, diag: &mut Diagnostic) { + diag.multipart_suggestion( + fluent::ast_lowering::use_angle_brackets, + vec![(self.open_param, String::from("<")), (self.close_param, String::from(">"))], + Applicability::MaybeIncorrect, + ); + } +} + +#[derive(SessionDiagnostic)] +#[help] +#[diag(ast_lowering::invalid_abi, code = "E0703")] +pub struct InvalidAbi { + #[primary_span] + #[label] + pub span: Span, + pub abi: Symbol, + pub valid_abis: String, +} + +#[derive(SessionDiagnostic, Clone, Copy)] +#[diag(ast_lowering::assoc_ty_parentheses)] +pub struct AssocTyParentheses { + #[primary_span] + pub span: Span, + #[subdiagnostic] + pub sub: AssocTyParenthesesSub, +} + +#[derive(Clone, Copy)] +pub enum AssocTyParenthesesSub { + Empty { parentheses_span: Span }, + NotEmpty { open_param: Span, close_param: Span }, +} + +impl AddSubdiagnostic for AssocTyParenthesesSub { + fn add_to_diagnostic(self, diag: &mut Diagnostic) { + match self { + Self::Empty { parentheses_span } => diag.multipart_suggestion( + fluent::ast_lowering::remove_parentheses, + vec![(parentheses_span, String::new())], + Applicability::MaybeIncorrect, + ), + Self::NotEmpty { open_param, close_param } => diag.multipart_suggestion( + fluent::ast_lowering::use_angle_brackets, + vec![(open_param, String::from("<")), (close_param, String::from(">"))], + Applicability::MaybeIncorrect, + ), + }; + } +} + +#[derive(SessionDiagnostic)] +#[diag(ast_lowering::misplaced_impl_trait, code = "E0562")] +pub struct MisplacedImplTrait<'a> { + #[primary_span] + pub span: Span, + pub position: DiagnosticArgFromDisplay<'a>, +} + +#[derive(SessionDiagnostic, Clone, Copy)] +#[diag(ast_lowering::rustc_box_attribute_error)] +pub struct RustcBoxAttributeError { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic, Clone, Copy)] +#[diag(ast_lowering::underscore_expr_lhs_assign)] +pub struct UnderscoreExprLhsAssign { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(SessionDiagnostic, Clone, Copy)] +#[diag(ast_lowering::base_expression_double_dot)] +pub struct BaseExpressionDoubleDot { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(SessionDiagnostic, Clone, Copy)] +#[diag(ast_lowering::await_only_in_async_fn_and_blocks, code = "E0728")] +pub struct AwaitOnlyInAsyncFnAndBlocks { + #[primary_span] + #[label] + pub dot_await_span: Span, + #[label(ast_lowering::this_not_async)] + pub item_span: Option<Span>, +} + +#[derive(SessionDiagnostic, Clone, Copy)] +#[diag(ast_lowering::generator_too_many_parameters, code = "E0628")] +pub struct GeneratorTooManyParameters { + #[primary_span] + pub fn_decl_span: Span, +} + +#[derive(SessionDiagnostic, Clone, Copy)] +#[diag(ast_lowering::closure_cannot_be_static, code = "E0697")] +pub struct ClosureCannotBeStatic { + #[primary_span] + pub fn_decl_span: Span, +} + +#[derive(SessionDiagnostic, Clone, Copy)] +#[help] +#[diag(ast_lowering::async_non_move_closure_not_supported, code = "E0708")] +pub struct AsyncNonMoveClosureNotSupported { + #[primary_span] + pub fn_decl_span: Span, +} + +#[derive(SessionDiagnostic, Clone, Copy)] +#[diag(ast_lowering::functional_record_update_destructuring_assignment)] +pub struct FunctionalRecordUpdateDestructuringAssignemnt { + #[primary_span] + #[suggestion(code = "", applicability = "machine-applicable")] + pub span: Span, +} + +#[derive(SessionDiagnostic, Clone, Copy)] +#[diag(ast_lowering::async_generators_not_supported, code = "E0727")] +pub struct AsyncGeneratorsNotSupported { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic, Clone, Copy)] +#[diag(ast_lowering::inline_asm_unsupported_target, code = "E0472")] +pub struct InlineAsmUnsupportedTarget { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic, Clone, Copy)] +#[diag(ast_lowering::att_syntax_only_x86)] +pub struct AttSyntaxOnlyX86 { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic, Clone, Copy)] +#[diag(ast_lowering::abi_specified_multiple_times)] +pub struct AbiSpecifiedMultipleTimes { + #[primary_span] + pub abi_span: Span, + pub prev_name: Symbol, + #[label] + pub prev_span: Span, + #[note] + pub equivalent: Option<()>, +} + +#[derive(SessionDiagnostic, Clone, Copy)] +#[diag(ast_lowering::clobber_abi_not_supported)] +pub struct ClobberAbiNotSupported { + #[primary_span] + pub abi_span: Span, +} + +#[derive(SessionDiagnostic)] +#[note] +#[diag(ast_lowering::invalid_abi_clobber_abi)] +pub struct InvalidAbiClobberAbi { + #[primary_span] + pub abi_span: Span, + pub supported_abis: String, +} + +#[derive(SessionDiagnostic, Clone, Copy)] +#[diag(ast_lowering::invalid_register)] +pub struct InvalidRegister<'a> { + #[primary_span] + pub op_span: Span, + pub reg: Symbol, + pub error: &'a str, +} + +#[derive(SessionDiagnostic, Clone, Copy)] +#[diag(ast_lowering::invalid_register_class)] +pub struct InvalidRegisterClass<'a> { + #[primary_span] + pub op_span: Span, + pub reg_class: Symbol, + pub error: &'a str, +} + +#[derive(SessionDiagnostic)] +#[diag(ast_lowering::invalid_asm_template_modifier_reg_class)] +pub struct InvalidAsmTemplateModifierRegClass { + #[primary_span] + #[label(ast_lowering::template_modifier)] + pub placeholder_span: Span, + #[label(ast_lowering::argument)] + pub op_span: Span, + #[subdiagnostic] + pub sub: InvalidAsmTemplateModifierRegClassSub, +} + +#[derive(SessionSubdiagnostic)] +pub enum InvalidAsmTemplateModifierRegClassSub { + #[note(ast_lowering::support_modifiers)] + SupportModifier { class_name: Symbol, modifiers: String }, + #[note(ast_lowering::does_not_support_modifiers)] + DoesNotSupportModifier { class_name: Symbol }, +} + +#[derive(SessionDiagnostic, Clone, Copy)] +#[diag(ast_lowering::invalid_asm_template_modifier_const)] +pub struct InvalidAsmTemplateModifierConst { + #[primary_span] + #[label(ast_lowering::template_modifier)] + pub placeholder_span: Span, + #[label(ast_lowering::argument)] + pub op_span: Span, +} + +#[derive(SessionDiagnostic, Clone, Copy)] +#[diag(ast_lowering::invalid_asm_template_modifier_sym)] +pub struct InvalidAsmTemplateModifierSym { + #[primary_span] + #[label(ast_lowering::template_modifier)] + pub placeholder_span: Span, + #[label(ast_lowering::argument)] + pub op_span: Span, +} + +#[derive(SessionDiagnostic, Clone, Copy)] +#[diag(ast_lowering::register_class_only_clobber)] +pub struct RegisterClassOnlyClobber { + #[primary_span] + pub op_span: Span, + pub reg_class_name: Symbol, +} + +#[derive(SessionDiagnostic, Clone, Copy)] +#[diag(ast_lowering::register_conflict)] +pub struct RegisterConflict<'a> { + #[primary_span] + #[label(ast_lowering::register1)] + pub op_span1: Span, + #[label(ast_lowering::register2)] + pub op_span2: Span, + pub reg1_name: &'a str, + pub reg2_name: &'a str, + #[help] + pub in_out: Option<Span>, +} + +#[derive(SessionDiagnostic, Clone, Copy)] +#[help] +#[diag(ast_lowering::sub_tuple_binding)] +pub struct SubTupleBinding<'a> { + #[primary_span] + #[label] + #[suggestion_verbose( + ast_lowering::sub_tuple_binding_suggestion, + code = "..", + applicability = "maybe-incorrect" + )] + pub span: Span, + pub ident: Ident, + pub ident_name: Symbol, + pub ctx: &'a str, +} + +#[derive(SessionDiagnostic, Clone, Copy)] +#[diag(ast_lowering::extra_double_dot)] +pub struct ExtraDoubleDot<'a> { + #[primary_span] + #[label] + pub span: Span, + #[label(ast_lowering::previously_used_here)] + pub prev_span: Span, + pub ctx: &'a str, +} + +#[derive(SessionDiagnostic, Clone, Copy)] +#[note] +#[diag(ast_lowering::misplaced_double_dot)] +pub struct MisplacedDoubleDot { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic, Clone, Copy)] +#[diag(ast_lowering::misplaced_relax_trait_bound)] +pub struct MisplacedRelaxTraitBound { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic, Clone, Copy)] +#[diag(ast_lowering::not_supported_for_lifetime_binder_async_closure)] +pub struct NotSupportedForLifetimeBinderAsyncClosure { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic, Clone, Copy)] +#[diag(ast_lowering::arbitrary_expression_in_pattern)] +pub struct ArbitraryExpressionInPattern { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic, Clone, Copy)] +#[diag(ast_lowering::inclusive_range_with_no_end)] +pub struct InclusiveRangeWithNoEnd { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic, Clone, Copy)] +#[diag(ast_lowering::trait_fn_async, code = "E0706")] +#[note] +#[note(ast_lowering::note2)] +pub struct TraitFnAsync { + #[primary_span] + pub fn_span: Span, + #[label] + pub span: Span, +} diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index fb6715ff1..7b8070d3c 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -1,19 +1,23 @@ +use super::errors::{ + AsyncGeneratorsNotSupported, AsyncNonMoveClosureNotSupported, AwaitOnlyInAsyncFnAndBlocks, + BaseExpressionDoubleDot, ClosureCannotBeStatic, FunctionalRecordUpdateDestructuringAssignemnt, + GeneratorTooManyParameters, InclusiveRangeWithNoEnd, NotSupportedForLifetimeBinderAsyncClosure, + RustcBoxAttributeError, UnderscoreExprLhsAssign, +}; use super::ResolverAstLoweringExt; use super::{ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericArgs}; use crate::{FnDeclKind, ImplTraitPosition}; - use rustc_ast::attr; use rustc_ast::ptr::P as AstP; use rustc_ast::*; use rustc_data_structures::stack::ensure_sufficient_stack; -use rustc_data_structures::thin_vec::ThinVec; -use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def::Res; use rustc_hir::definitions::DefPathData; use rustc_span::source_map::{respan, DesugaringKind, Span, Spanned}; use rustc_span::symbol::{sym, Ident}; use rustc_span::DUMMY_SP; +use thin_vec::thin_vec; impl<'hir> LoweringContext<'_, 'hir> { fn lower_exprs(&mut self, exprs: &[AstP<Expr>]) -> &'hir [hir::Expr<'hir>] { @@ -46,13 +50,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let hir_id = self.lower_node_id(e.id); return hir::Expr { hir_id, kind, span: self.lower_span(e.span) }; } else { - self.tcx.sess - .struct_span_err( - e.span, - "#[rustc_box] requires precisely one argument \ - and no other attributes are allowed", - ) - .emit(); + self.tcx.sess.emit_err(RustcBoxAttributeError { span: e.span }); hir::ExprKind::Err } } else if let Some(legacy_args) = self.resolver.legacy_const_generic_args(f) { @@ -68,10 +66,12 @@ impl<'hir> LoweringContext<'_, 'hir> { seg, ParamMode::Optional, ParenthesizedGenericArgs::Err, - ImplTraitContext::Disallowed(ImplTraitPosition::Path), + &ImplTraitContext::Disallowed(ImplTraitPosition::Path), )); - let args = self.lower_exprs(args); - hir::ExprKind::MethodCall(hir_seg, args, self.lower_span(span)) + let receiver = self.lower_expr(&args[0]); + let args = + self.arena.alloc_from_iter(args[1..].iter().map(|x| self.lower_expr_mut(x))); + hir::ExprKind::MethodCall(hir_seg, receiver, args, self.lower_span(span)) } ExprKind::Binary(binop, ref lhs, ref rhs) => { let binop = self.lower_binop(binop); @@ -90,13 +90,13 @@ impl<'hir> LoweringContext<'_, 'hir> { ExprKind::Cast(ref expr, ref ty) => { let expr = self.lower_expr(expr); let ty = - self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)); + self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)); hir::ExprKind::Cast(expr, ty) } ExprKind::Type(ref expr, ref ty) => { let expr = self.lower_expr(expr); let ty = - self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)); + self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)); hir::ExprKind::Type(expr, ty) } ExprKind::AddrOf(k, m, ref ohs) => { @@ -146,13 +146,19 @@ impl<'hir> LoweringContext<'_, 'hir> { |this| this.with_new_scopes(|this| this.lower_block_expr(block)), ), ExprKind::Await(ref expr) => { - let span = if expr.span.hi() < e.span.hi() { - expr.span.shrink_to_hi().with_hi(e.span.hi()) + let dot_await_span = if expr.span.hi() < e.span.hi() { + let span_with_whitespace = self + .tcx + .sess + .source_map() + .span_extend_while(expr.span, char::is_whitespace) + .unwrap_or(expr.span); + span_with_whitespace.shrink_to_hi().with_hi(e.span.hi()) } else { // this is a recovered `await expr` e.span }; - self.lower_expr_await(span, expr) + self.lower_expr_await(dot_await_span, expr) } ExprKind::Closure( ref binder, @@ -210,13 +216,7 @@ impl<'hir> LoweringContext<'_, 'hir> { self.lower_expr_range(e.span, e1.as_deref(), e2.as_deref(), lims) } ExprKind::Underscore => { - self.tcx - .sess.struct_span_err( - e.span, - "in expressions, `_` can only be used on the left-hand side of an assignment", - ) - .span_label(e.span, "`_` not allowed here") - .emit(); + self.tcx.sess.emit_err(UnderscoreExprLhsAssign { span: e.span }); hir::ExprKind::Err } ExprKind::Path(ref qself, ref path) => { @@ -225,7 +225,7 @@ impl<'hir> LoweringContext<'_, 'hir> { qself, path, ParamMode::Optional, - ImplTraitContext::Disallowed(ImplTraitPosition::Path), + &ImplTraitContext::Disallowed(ImplTraitPosition::Path), ); hir::ExprKind::Path(qpath) } @@ -248,11 +248,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let rest = match &se.rest { StructRest::Base(e) => Some(self.lower_expr(e)), StructRest::Rest(sp) => { - self.tcx - .sess - .struct_span_err(*sp, "base expression required after `..`") - .span_label(*sp, "add a base expression here") - .emit(); + self.tcx.sess.emit_err(BaseExpressionDoubleDot { span: *sp }); Some(&*self.arena.alloc(self.expr_err(*sp))) } StructRest::None => None, @@ -263,7 +259,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &se.qself, &se.path, ParamMode::Optional, - ImplTraitContext::Disallowed(ImplTraitPosition::Path), + &ImplTraitContext::Disallowed(ImplTraitPosition::Path), )), self.arena .alloc_from_iter(se.fields.iter().map(|x| self.lower_expr_field(x))), @@ -446,12 +442,12 @@ impl<'hir> LoweringContext<'_, 'hir> { let lowered_cond = self.with_loop_condition_scope(|t| t.lower_expr(cond)); let new_cond = self.manage_let_cond(lowered_cond); let then = self.lower_block_expr(body); - let expr_break = self.expr_break(span, ThinVec::new()); + let expr_break = self.expr_break(span, AttrVec::new()); let stmt_break = self.stmt_expr(span, expr_break); let else_blk = self.block_all(span, arena_vec![self; stmt_break], None); - let else_expr = self.arena.alloc(self.expr_block(else_blk, ThinVec::new())); + let else_expr = self.arena.alloc(self.expr_block(else_blk, AttrVec::new())); let if_kind = hir::ExprKind::If(new_cond, self.arena.alloc(then), Some(else_expr)); - let if_expr = self.expr(span, if_kind, ThinVec::new()); + let if_expr = self.expr(span, if_kind, AttrVec::new()); let block = self.block_expr(self.arena.alloc(if_expr)); let span = self.lower_span(span.with_hi(cond.span.hi())); let opt_label = self.lower_label(opt_label); @@ -510,7 +506,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let constructor = self.arena.alloc(self.expr_lang_item_path( method_span, lang_item, - ThinVec::new(), + AttrVec::new(), None, )); self.expr_call(overall_span, constructor, std::slice::from_ref(expr)) @@ -562,7 +558,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ) -> hir::ExprKind<'hir> { let output = match ret_ty { Some(ty) => hir::FnRetTy::Return( - self.lower_ty(&ty, ImplTraitContext::Disallowed(ImplTraitPosition::AsyncBlock)), + self.lower_ty(&ty, &ImplTraitContext::Disallowed(ImplTraitPosition::AsyncBlock)), ), None => hir::FnRetTy::DefaultReturn(self.lower_span(span)), }; @@ -587,7 +583,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let (pat, task_context_hid) = self.pat_ident_binding_mode( span, Ident::with_dummy_span(sym::_task_context), - hir::BindingAnnotation::Mutable, + hir::BindingAnnotation::MUT, ); let param = hir::Param { hir_id: self.next_id(), @@ -633,7 +629,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let gen_future = self.expr_lang_item_path( unstable_span, hir::LangItem::FromGenerator, - ThinVec::new(), + AttrVec::new(), None, ); @@ -661,17 +657,10 @@ impl<'hir> LoweringContext<'_, 'hir> { match self.generator_kind { Some(hir::GeneratorKind::Async(_)) => {} Some(hir::GeneratorKind::Gen) | None => { - let mut err = struct_span_err!( - self.tcx.sess, + self.tcx.sess.emit_err(AwaitOnlyInAsyncFnAndBlocks { dot_await_span, - E0728, - "`await` is only allowed inside `async` functions and blocks" - ); - err.span_label(dot_await_span, "only allowed inside `async` functions and blocks"); - if let Some(item_sp) = self.current_item { - err.span_label(item_sp, "this is not `async`"); - } - err.emit(); + item_span: self.current_item, + }); } } let span = self.mark_span_with_reason(DesugaringKind::Await, dot_await_span, None); @@ -688,7 +677,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // this name to identify what is being awaited by a suspended async functions. let awaitee_ident = Ident::with_dummy_span(sym::__awaitee); let (awaitee_pat, awaitee_pat_hid) = - self.pat_ident_binding_mode(span, awaitee_ident, hir::BindingAnnotation::Mutable); + self.pat_ident_binding_mode(span, awaitee_ident, hir::BindingAnnotation::MUT); let task_context_ident = Ident::with_dummy_span(sym::_task_context); @@ -745,7 +734,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let break_x = self.with_loop_scope(loop_node_id, move |this| { let expr_break = hir::ExprKind::Break(this.lower_loop_destination(None), Some(x_expr)); - this.arena.alloc(this.expr(gen_future_span, expr_break, ThinVec::new())) + this.arena.alloc(this.expr(gen_future_span, expr_break, AttrVec::new())) }); self.arm(ready_pat, break_x) }; @@ -778,7 +767,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let yield_expr = self.expr( span, hir::ExprKind::Yield(unit, hir::YieldSource::Await { expr: Some(expr_hir_id) }), - ThinVec::new(), + AttrVec::new(), ); let yield_expr = self.arena.alloc(yield_expr); @@ -866,7 +855,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params); // Lower outside new scope to preserve `is_in_loop_condition`. - let fn_decl = self.lower_fn_decl(decl, None, FnDeclKind::Closure, None); + let fn_decl = self.lower_fn_decl(decl, None, fn_decl_span, FnDeclKind::Closure, None); let c = self.arena.alloc(hir::Closure { binder: binder_clause, @@ -891,13 +880,7 @@ impl<'hir> LoweringContext<'_, 'hir> { match generator_kind { Some(hir::GeneratorKind::Gen) => { if decl.inputs.len() > 1 { - struct_span_err!( - self.tcx.sess, - fn_decl_span, - E0628, - "too many parameters for a generator (expected 0 or 1 parameters)" - ) - .emit(); + self.tcx.sess.emit_err(GeneratorTooManyParameters { fn_decl_span }); } Some(movability) } @@ -906,13 +889,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } None => { if movability == Movability::Static { - struct_span_err!( - self.tcx.sess, - fn_decl_span, - E0697, - "closures cannot be static" - ) - .emit(); + self.tcx.sess.emit_err(ClosureCannotBeStatic { fn_decl_span }); } None } @@ -945,10 +922,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn_decl_span: Span, ) -> hir::ExprKind<'hir> { if let &ClosureBinder::For { span, .. } = binder { - self.tcx.sess.span_err( - span, - "`for<...>` binders on `async` closures are not currently supported", - ); + self.tcx.sess.emit_err(NotSupportedForLifetimeBinderAsyncClosure { span }); } let (binder_clause, generic_params) = self.lower_closure_binder(binder); @@ -959,17 +933,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let body = self.with_new_scopes(|this| { // FIXME(cramertj): allow `async` non-`move` closures with arguments. if capture_clause == CaptureBy::Ref && !decl.inputs.is_empty() { - struct_span_err!( - this.tcx.sess, - fn_decl_span, - E0708, - "`async` non-`move` closures with parameters are not currently supported", - ) - .help( - "consider using `let` statements to manually capture \ - variables by reference before entering an `async move` closure", - ) - .emit(); + this.tcx.sess.emit_err(AsyncNonMoveClosureNotSupported { fn_decl_span }); } // Transform `async |x: u8| -> X { ... }` into @@ -985,17 +949,17 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::AsyncGeneratorKind::Closure, |this| this.with_new_scopes(|this| this.lower_expr_mut(body)), ); - this.expr(fn_decl_span, async_body, ThinVec::new()) + this.expr(fn_decl_span, async_body, AttrVec::new()) }); body_id }); let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params); - // We need to lower the declaration outside the new scope, because we // have to conserve the state of being inside a loop condition for the // closure argument types. - let fn_decl = self.lower_fn_decl(&outer_decl, None, FnDeclKind::Closure, None); + let fn_decl = + self.lower_fn_decl(&outer_decl, None, fn_decl_span, FnDeclKind::Closure, None); let c = self.arena.alloc(hir::Closure { binder: binder_clause, @@ -1165,11 +1129,14 @@ impl<'hir> LoweringContext<'_, 'hir> { qself, path, ParamMode::Optional, - ImplTraitContext::Disallowed(ImplTraitPosition::Path), + &ImplTraitContext::Disallowed(ImplTraitPosition::Path), ); // Destructure like a tuple struct. - let tuple_struct_pat = - hir::PatKind::TupleStruct(qpath, pats, rest.map(|r| r.0)); + let tuple_struct_pat = hir::PatKind::TupleStruct( + qpath, + pats, + hir::DotDotPos::new(rest.map(|r| r.0)), + ); return self.pat_without_dbm(lhs.span, tuple_struct_pat); } } @@ -1181,7 +1148,7 @@ impl<'hir> LoweringContext<'_, 'hir> { qself, path, ParamMode::Optional, - ImplTraitContext::Disallowed(ImplTraitPosition::Path), + &ImplTraitContext::Disallowed(ImplTraitPosition::Path), ); // Destructure like a unit struct. let unit_struct_pat = hir::PatKind::Path(qpath); @@ -1205,24 +1172,13 @@ impl<'hir> LoweringContext<'_, 'hir> { &se.qself, &se.path, ParamMode::Optional, - ImplTraitContext::Disallowed(ImplTraitPosition::Path), + &ImplTraitContext::Disallowed(ImplTraitPosition::Path), ); let fields_omitted = match &se.rest { StructRest::Base(e) => { - self.tcx - .sess - .struct_span_err( - e.span, - "functional record updates are not allowed in destructuring \ - assignments", - ) - .span_suggestion( - e.span, - "consider removing the trailing pattern", - "", - rustc_errors::Applicability::MachineApplicable, - ) - .emit(); + self.tcx.sess.emit_err(FunctionalRecordUpdateDestructuringAssignemnt { + span: e.span, + }); true } StructRest::Rest(_) => true, @@ -1235,13 +1191,13 @@ impl<'hir> LoweringContext<'_, 'hir> { ExprKind::Tup(elements) => { let (pats, rest) = self.destructure_sequence(elements, "tuple", eq_sign_span, assignments); - let tuple_pat = hir::PatKind::Tuple(pats, rest.map(|r| r.0)); + let tuple_pat = hir::PatKind::Tuple(pats, hir::DotDotPos::new(rest.map(|r| r.0))); return self.pat_without_dbm(lhs.span, tuple_pat); } ExprKind::Paren(e) => { // We special-case `(..)` for consistency with patterns. if let ExprKind::Range(None, None, RangeLimits::HalfOpen) = e.kind { - let tuple_pat = hir::PatKind::Tuple(&[], Some(0)); + let tuple_pat = hir::PatKind::Tuple(&[], hir::DotDotPos::new(Some(0))); return self.pat_without_dbm(lhs.span, tuple_pat); } else { return self.destructure_assign_mut(e, eq_sign_span, assignments); @@ -1255,7 +1211,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let ident = self.expr_ident(lhs.span, ident, binding); let assign = hir::ExprKind::Assign(self.lower_expr(lhs), ident, self.lower_span(eq_sign_span)); - let expr = self.expr(lhs.span, assign, ThinVec::new()); + let expr = self.expr(lhs.span, assign, AttrVec::new()); assignments.push(self.stmt_expr(lhs.span, expr)); pat } @@ -1297,7 +1253,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let fn_path = hir::QPath::LangItem(hir::LangItem::RangeInclusiveNew, self.lower_span(span), None); let fn_expr = - self.arena.alloc(self.expr(span, hir::ExprKind::Path(fn_path), ThinVec::new())); + self.arena.alloc(self.expr(span, hir::ExprKind::Path(fn_path), AttrVec::new())); hir::ExprKind::Call(fn_expr, arena_vec![self; e1, e2]) } @@ -1317,7 +1273,13 @@ impl<'hir> LoweringContext<'_, 'hir> { (Some(..), Some(..), HalfOpen) => hir::LangItem::Range, (None, Some(..), Closed) => hir::LangItem::RangeToInclusive, (Some(..), Some(..), Closed) => unreachable!(), - (_, None, Closed) => self.diagnostic().span_fatal(span, "inclusive range with no end"), + (start, None, Closed) => { + self.tcx.sess.emit_err(InclusiveRangeWithNoEnd { span }); + match start { + Some(..) => hir::LangItem::RangeFrom, + None => hir::LangItem::RangeFull, + } + } }; let fields = self.arena.alloc_from_iter( @@ -1404,8 +1366,10 @@ impl<'hir> LoweringContext<'_, 'hir> { } fn lower_expr_field(&mut self, f: &ExprField) -> hir::ExprField<'hir> { + let hir_id = self.lower_node_id(f.id); + self.lower_attrs(hir_id, &f.attrs); hir::ExprField { - hir_id: self.next_id(), + hir_id, ident: self.lower_ident(f.ident), expr: self.lower_expr(&f.expr), span: self.lower_span(f.span), @@ -1417,13 +1381,7 @@ impl<'hir> LoweringContext<'_, 'hir> { match self.generator_kind { Some(hir::GeneratorKind::Gen) => {} Some(hir::GeneratorKind::Async(_)) => { - struct_span_err!( - self.tcx.sess, - span, - E0727, - "`async` generators are not yet supported" - ) - .emit(); + self.tcx.sess.emit_err(AsyncGeneratorsNotSupported { span }); } None => self.generator_kind = Some(hir::GeneratorKind::Gen), } @@ -1468,7 +1426,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // `None => break` let none_arm = { let break_expr = - self.with_loop_scope(e.id, |this| this.expr_break_alloc(for_span, ThinVec::new())); + self.with_loop_scope(e.id, |this| this.expr_break_alloc(for_span, AttrVec::new())); let pat = self.pat_none(for_span); self.arm(pat, break_expr) }; @@ -1477,14 +1435,14 @@ impl<'hir> LoweringContext<'_, 'hir> { let some_arm = { let some_pat = self.pat_some(pat_span, pat); let body_block = self.with_loop_scope(e.id, |this| this.lower_block(body, false)); - let body_expr = self.arena.alloc(self.expr_block(body_block, ThinVec::new())); + let body_expr = self.arena.alloc(self.expr_block(body_block, AttrVec::new())); self.arm(some_pat, body_expr) }; // `mut iter` let iter = Ident::with_dummy_span(sym::iter); let (iter_pat, iter_pat_nid) = - self.pat_ident_binding_mode(head_span, iter, hir::BindingAnnotation::Mutable); + self.pat_ident_binding_mode(head_span, iter, hir::BindingAnnotation::MUT); // `match Iterator::next(&mut iter) { ... }` let match_expr = { @@ -1534,15 +1492,13 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::MatchSource::ForLoopDesugar, )); - let attrs: Vec<_> = e.attrs.iter().map(|a| self.lower_attr(a)).collect(); - // This is effectively `{ let _result = ...; _result }`. // The construct was introduced in #21984 and is necessary to make sure that // temporaries in the `head` expression are dropped and do not leak to the // surrounding scope of the `match` since the `match` is not a terminating scope. // // Also, add the attributes to the outer returned expr node. - self.expr_drop_temps_mut(for_span, match_expr, attrs.into()) + self.expr_drop_temps_mut(for_span, match_expr, e.attrs.clone()) } /// Desugar `ExprKind::Try` from: `<expr>?` into: @@ -1592,9 +1548,9 @@ impl<'hir> LoweringContext<'_, 'hir> { let uc_nested = attr::mk_nested_word_item(uc_ident); attr::mk_list_item(allow_ident, vec![uc_nested]) }; - attr::mk_attr_outer(allow) + attr::mk_attr_outer(&self.tcx.sess.parse_sess.attr_id_generator, allow) }; - let attrs = vec![attr]; + let attrs: AttrVec = thin_vec![attr]; // `ControlFlow::Continue(val) => #[allow(unreachable_code)] val,` let continue_arm = { @@ -1604,7 +1560,7 @@ impl<'hir> LoweringContext<'_, 'hir> { span, val_ident, val_pat_nid, - ThinVec::from(attrs.clone()), + attrs.clone(), )); let continue_pat = self.pat_cf_continue(unstable_span, val_pat); self.arm(continue_pat, val_expr) @@ -1623,7 +1579,6 @@ impl<'hir> LoweringContext<'_, 'hir> { self.arena.alloc(residual_expr), unstable_span, ); - let thin_attrs = ThinVec::from(attrs); let ret_expr = if let Some(catch_node) = self.catch_scope { let target_id = Ok(self.lower_node_id(catch_node)); self.arena.alloc(self.expr( @@ -1632,13 +1587,13 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::Destination { label: None, target_id }, Some(from_residual_expr), ), - thin_attrs, + attrs, )) } else { self.arena.alloc(self.expr( try_span, hir::ExprKind::Ret(Some(from_residual_expr)), - thin_attrs, + attrs, )) }; @@ -1726,7 +1681,7 @@ impl<'hir> LoweringContext<'_, 'hir> { arms: &'hir [hir::Arm<'hir>], source: hir::MatchSource, ) -> hir::Expr<'hir> { - self.expr(span, hir::ExprKind::Match(arg, arms, source), ThinVec::new()) + self.expr(span, hir::ExprKind::Match(arg, arms, source), AttrVec::new()) } fn expr_break(&mut self, span: Span, attrs: AttrVec) -> hir::Expr<'hir> { @@ -1743,12 +1698,12 @@ impl<'hir> LoweringContext<'_, 'hir> { self.expr( span, hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Mut, e), - ThinVec::new(), + AttrVec::new(), ) } fn expr_unit(&mut self, sp: Span) -> &'hir hir::Expr<'hir> { - self.arena.alloc(self.expr(sp, hir::ExprKind::Tup(&[]), ThinVec::new())) + self.arena.alloc(self.expr(sp, hir::ExprKind::Tup(&[]), AttrVec::new())) } fn expr_call_mut( @@ -1757,7 +1712,7 @@ impl<'hir> LoweringContext<'_, 'hir> { e: &'hir hir::Expr<'hir>, args: &'hir [hir::Expr<'hir>], ) -> hir::Expr<'hir> { - self.expr(span, hir::ExprKind::Call(e, args), ThinVec::new()) + self.expr(span, hir::ExprKind::Call(e, args), AttrVec::new()) } fn expr_call( @@ -1777,7 +1732,7 @@ impl<'hir> LoweringContext<'_, 'hir> { hir_id: Option<hir::HirId>, ) -> hir::Expr<'hir> { let path = - self.arena.alloc(self.expr_lang_item_path(span, lang_item, ThinVec::new(), hir_id)); + self.arena.alloc(self.expr_lang_item_path(span, lang_item, AttrVec::new(), hir_id)); self.expr_call_mut(span, path, args) } @@ -1820,7 +1775,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ident: Ident, binding: hir::HirId, ) -> hir::Expr<'hir> { - self.expr_ident_with_attrs(sp, ident, binding, ThinVec::new()) + self.expr_ident_with_attrs(sp, ident, binding, AttrVec::new()) } fn expr_ident_with_attrs( @@ -1830,12 +1785,14 @@ impl<'hir> LoweringContext<'_, 'hir> { binding: hir::HirId, attrs: AttrVec, ) -> hir::Expr<'hir> { + let hir_id = self.next_id(); + let res = Res::Local(binding); let expr_path = hir::ExprKind::Path(hir::QPath::Resolved( None, self.arena.alloc(hir::Path { span: self.lower_span(span), - res: Res::Local(binding), - segments: arena_vec![self; hir::PathSegment::from_ident(ident)], + res, + segments: arena_vec![self; hir::PathSegment::new(ident, hir_id, res)], }), )); @@ -1858,13 +1815,13 @@ impl<'hir> LoweringContext<'_, 'hir> { }), None, ), - ThinVec::new(), + AttrVec::new(), ) } fn expr_block_empty(&mut self, span: Span) -> &'hir hir::Expr<'hir> { let blk = self.block_all(span, &[], None); - let expr = self.expr_block(blk, ThinVec::new()); + let expr = self.expr_block(blk, AttrVec::new()); self.arena.alloc(expr) } diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs index d5af74d47..85846b567 100644 --- a/compiler/rustc_ast_lowering/src/index.rs +++ b/compiler/rustc_ast_lowering/src/index.rs @@ -11,8 +11,6 @@ use rustc_session::Session; use rustc_span::source_map::SourceMap; use rustc_span::{Span, DUMMY_SP}; -use tracing::debug; - /// A visitor that walks over the HIR and collects `Node`s into a HIR map. pub(super) struct NodeCollector<'a, 'hir> { /// Source map @@ -31,7 +29,7 @@ pub(super) struct NodeCollector<'a, 'hir> { definitions: &'a definitions::Definitions, } -#[tracing::instrument(level = "debug", skip(sess, definitions, bodies))] +#[instrument(level = "debug", skip(sess, definitions, bodies))] pub(super) fn index_hir<'hir>( sess: &Session, definitions: &definitions::Definitions, @@ -67,10 +65,11 @@ pub(super) fn index_hir<'hir>( } impl<'a, 'hir> NodeCollector<'a, 'hir> { - #[tracing::instrument(level = "debug", skip(self))] + #[instrument(level = "debug", skip(self))] fn insert(&mut self, span: Span, hir_id: HirId, node: Node<'hir>) { debug_assert_eq!(self.owner, hir_id.owner); debug_assert_ne!(hir_id.local_id.as_u32(), 0); + debug_assert_ne!(hir_id.local_id, self.parent_node); // Make sure that the DepNode of some node coincides with the HirId // owner of that node. @@ -142,7 +141,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { }); } - #[tracing::instrument(level = "debug", skip(self))] + #[instrument(level = "debug", skip(self))] fn visit_item(&mut self, i: &'hir Item<'hir>) { debug_assert_eq!(i.def_id, self.owner); self.with_parent(i.hir_id(), |this| { @@ -156,7 +155,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { }); } - #[tracing::instrument(level = "debug", skip(self))] + #[instrument(level = "debug", skip(self))] fn visit_foreign_item(&mut self, fi: &'hir ForeignItem<'hir>) { debug_assert_eq!(fi.def_id, self.owner); self.with_parent(fi.hir_id(), |this| { @@ -175,7 +174,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { }) } - #[tracing::instrument(level = "debug", skip(self))] + #[instrument(level = "debug", skip(self))] fn visit_trait_item(&mut self, ti: &'hir TraitItem<'hir>) { debug_assert_eq!(ti.def_id, self.owner); self.with_parent(ti.hir_id(), |this| { @@ -183,7 +182,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { }); } - #[tracing::instrument(level = "debug", skip(self))] + #[instrument(level = "debug", skip(self))] fn visit_impl_item(&mut self, ii: &'hir ImplItem<'hir>) { debug_assert_eq!(ii.def_id, self.owner); self.with_parent(ii.hir_id(), |this| { @@ -199,6 +198,13 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { }); } + fn visit_pat_field(&mut self, field: &'hir PatField<'hir>) { + self.insert(field.span, field.hir_id, Node::PatField(field)); + self.with_parent(field.hir_id, |this| { + intravisit::walk_pat_field(this, field); + }); + } + fn visit_arm(&mut self, arm: &'hir Arm<'hir>) { let node = Node::Arm(arm); @@ -225,6 +231,13 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { }); } + fn visit_expr_field(&mut self, field: &'hir ExprField<'hir>) { + self.insert(field.span, field.hir_id, Node::ExprField(field)); + self.with_parent(field.hir_id, |this| { + intravisit::walk_expr_field(this, field); + }); + } + fn visit_stmt(&mut self, stmt: &'hir Stmt<'hir>) { self.insert(stmt.span, stmt.hir_id, Node::Stmt(stmt)); @@ -233,11 +246,9 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { }); } - fn visit_path_segment(&mut self, path_span: Span, path_segment: &'hir PathSegment<'hir>) { - if let Some(hir_id) = path_segment.hir_id { - self.insert(path_span, hir_id, Node::PathSegment(path_segment)); - } - intravisit::walk_path_segment(self, path_span, path_segment); + fn visit_path_segment(&mut self, path_segment: &'hir PathSegment<'hir>) { + self.insert(path_segment.ident.span, path_segment.hir_id, Node::PathSegment(path_segment)); + intravisit::walk_path_segment(self, path_segment); } fn visit_ty(&mut self, ty: &'hir Ty<'hir>) { @@ -269,12 +280,12 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { fk: intravisit::FnKind<'hir>, fd: &'hir FnDecl<'hir>, b: BodyId, - s: Span, + _: Span, id: HirId, ) { assert_eq!(self.owner, id.owner); assert_eq!(self.parent_node, id.local_id); - intravisit::walk_fn(self, fk, fd, b, s, id); + intravisit::walk_fn(self, fk, fd, b, id); } fn visit_block(&mut self, block: &'hir Block<'hir>) { @@ -295,14 +306,14 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { self.insert(lifetime.span, lifetime.hir_id, Node::Lifetime(lifetime)); } - fn visit_variant(&mut self, v: &'hir Variant<'hir>, g: &'hir Generics<'hir>, item_id: HirId) { + fn visit_variant(&mut self, v: &'hir Variant<'hir>) { self.insert(v.span, v.id, Node::Variant(v)); self.with_parent(v.id, |this| { // Register the constructor of this variant. if let Some(ctor_hir_id) = v.data.ctor_hir_id() { this.insert(v.span, ctor_hir_id, Node::Ctor(&v.data)); } - intravisit::walk_variant(this, v, g, item_id); + intravisit::walk_variant(this, v); }); } diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index ee4c0036f..550833275 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1,5 +1,6 @@ +use super::errors::{InvalidAbi, MisplacedRelaxTraitBound}; use super::ResolverAstLoweringExt; -use super::{AstOwner, ImplTraitContext, ImplTraitPosition}; +use super::{Arena, AstOwner, ImplTraitContext, ImplTraitPosition}; use super::{FnDeclKind, LoweringContext, ParamMode}; use rustc_ast::ptr::P; @@ -7,7 +8,6 @@ use rustc_ast::visit::AssocCtxt; use rustc_ast::*; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sorted_map::SortedMap; -use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID}; @@ -25,6 +25,7 @@ use std::iter; pub(super) struct ItemLowerer<'a, 'hir> { pub(super) tcx: TyCtxt<'hir>, pub(super) resolver: &'a mut ResolverAstLowering, + pub(super) ast_arena: &'a Arena<'static>, pub(super) ast_index: &'a IndexVec<LocalDefId, AstOwner<'a>>, pub(super) owners: &'a mut IndexVec<LocalDefId, hir::MaybeOwner<&'hir hir::OwnerInfo<'hir>>>, } @@ -60,6 +61,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { tcx: self.tcx, resolver: self.resolver, arena: self.tcx.hir_arena, + ast_arena: self.ast_arena, // HirId handling. bodies: Vec::new(), @@ -85,6 +87,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { allow_try_trait: Some([sym::try_trait_v2, sym::yeet_desugar_details][..].into()), allow_gen_future: Some([sym::gen_future][..].into()), allow_into_future: Some([sym::into_future][..].into()), + generics_def_id_map: Default::default(), }; lctx.with_hir_id_owner(owner, |lctx| f(lctx)); @@ -120,7 +123,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { self.with_lctx(CRATE_NODE_ID, |lctx| { let module = lctx.lower_mod(&c.items, &c.spans); lctx.lower_attrs(hir::CRATE_HIR_ID, &c.attrs); - hir::OwnerNode::Crate(lctx.arena.alloc(module)) + hir::OwnerNode::Crate(module) }) } @@ -158,14 +161,18 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { } impl<'hir> LoweringContext<'_, 'hir> { - pub(super) fn lower_mod(&mut self, items: &[P<Item>], spans: &ModSpans) -> hir::Mod<'hir> { - hir::Mod { + pub(super) fn lower_mod( + &mut self, + items: &[P<Item>], + spans: &ModSpans, + ) -> &'hir hir::Mod<'hir> { + self.arena.alloc(hir::Mod { spans: hir::ModSpans { inner_span: self.lower_span(spans.inner_span), inject_use_span: self.lower_span(spans.inject_use_span), }, item_ids: self.arena.alloc_from_iter(items.iter().flat_map(|x| self.lower_item_ref(x))), - } + }) } pub(super) fn lower_item_ref(&mut self, i: &Item) -> SmallVec<[hir::ItemId; 1]> { @@ -259,10 +266,10 @@ impl<'hir> LoweringContext<'_, 'hir> { let body_id = this.lower_maybe_async_body(span, &decl, asyncness, body.as_deref()); - let itctx = ImplTraitContext::Universal; - let (generics, decl) = this.lower_generics(generics, id, itctx, |this| { + let mut itctx = ImplTraitContext::Universal; + let (generics, decl) = this.lower_generics(generics, id, &mut itctx, |this| { let ret_id = asyncness.opt_return_id(); - this.lower_fn_decl(&decl, Some(id), FnDeclKind::Fn, ret_id) + this.lower_fn_decl(&decl, Some(id), fn_sig_span, FnDeclKind::Fn, ret_id) }); let sig = hir::FnSig { decl, @@ -306,8 +313,8 @@ impl<'hir> LoweringContext<'_, 'hir> { let (generics, ty) = self.lower_generics( &generics, id, - ImplTraitContext::Disallowed(ImplTraitPosition::Generic), - |this| this.lower_ty(ty, ImplTraitContext::TypeAliasesOpaqueTy), + &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + |this| this.lower_ty(ty, &ImplTraitContext::TypeAliasesOpaqueTy), ); hir::ItemKind::TyAlias(ty, generics) } @@ -319,7 +326,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let (generics, ty) = self.lower_generics( &generics, id, - ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| this.arena.alloc(this.ty(span, hir::TyKind::Err)), ); hir::ItemKind::TyAlias(ty, generics) @@ -328,7 +335,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let (generics, variants) = self.lower_generics( generics, id, - ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| { this.arena.alloc_from_iter( enum_definition.variants.iter().map(|x| this.lower_variant(x)), @@ -341,7 +348,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let (generics, struct_def) = self.lower_generics( generics, id, - ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| this.lower_variant_data(hir_id, struct_def), ); hir::ItemKind::Struct(struct_def, generics) @@ -350,7 +357,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let (generics, vdata) = self.lower_generics( generics, id, - ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| this.lower_variant_data(hir_id, vdata), ); hir::ItemKind::Union(vdata, generics) @@ -378,18 +385,18 @@ impl<'hir> LoweringContext<'_, 'hir> { // method, it will not be considered an in-band // lifetime to be added, but rather a reference to a // parent lifetime. - let itctx = ImplTraitContext::Universal; + let mut itctx = ImplTraitContext::Universal; let (generics, (trait_ref, lowered_ty)) = - self.lower_generics(ast_generics, id, itctx, |this| { + self.lower_generics(ast_generics, id, &mut itctx, |this| { let trait_ref = trait_ref.as_ref().map(|trait_ref| { this.lower_trait_ref( trait_ref, - ImplTraitContext::Disallowed(ImplTraitPosition::Trait), + &ImplTraitContext::Disallowed(ImplTraitPosition::Trait), ) }); let lowered_ty = this - .lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)); + .lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)); (trait_ref, lowered_ty) }); @@ -428,11 +435,11 @@ impl<'hir> LoweringContext<'_, 'hir> { let (generics, (unsafety, items, bounds)) = self.lower_generics( generics, id, - ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| { let bounds = this.lower_param_bounds( bounds, - ImplTraitContext::Disallowed(ImplTraitPosition::Bound), + &ImplTraitContext::Disallowed(ImplTraitPosition::Bound), ); let items = this.arena.alloc_from_iter( items.iter().map(|item| this.lower_trait_item_ref(item)), @@ -447,11 +454,11 @@ impl<'hir> LoweringContext<'_, 'hir> { let (generics, bounds) = self.lower_generics( generics, id, - ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| { this.lower_param_bounds( bounds, - ImplTraitContext::Disallowed(ImplTraitPosition::Bound), + &ImplTraitContext::Disallowed(ImplTraitPosition::Bound), ) }, ); @@ -474,7 +481,7 @@ impl<'hir> LoweringContext<'_, 'hir> { span: Span, body: Option<&Expr>, ) -> (&'hir hir::Ty<'hir>, hir::BodyId) { - let ty = self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)); + let ty = self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)); (ty, self.lower_const_body(span, body)) } @@ -647,12 +654,18 @@ impl<'hir> LoweringContext<'_, 'hir> { kind: match i.kind { ForeignItemKind::Fn(box Fn { ref sig, ref generics, .. }) => { let fdec = &sig.decl; - let itctx = ImplTraitContext::Universal; + let mut itctx = ImplTraitContext::Universal; let (generics, (fn_dec, fn_args)) = - self.lower_generics(generics, i.id, itctx, |this| { + self.lower_generics(generics, i.id, &mut itctx, |this| { ( // Disallow `impl Trait` in foreign items. - this.lower_fn_decl(fdec, None, FnDeclKind::ExternFn, None), + this.lower_fn_decl( + fdec, + None, + sig.span, + FnDeclKind::ExternFn, + None, + ), this.lower_fn_params_to_names(fdec), ) }); @@ -661,7 +674,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } ForeignItemKind::Static(ref t, m, _) => { let ty = - self.lower_ty(t, ImplTraitContext::Disallowed(ImplTraitPosition::Type)); + self.lower_ty(t, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)); hir::ForeignItemKind::Static(ty, m) } ForeignItemKind::TyAlias(..) => hir::ForeignItemKind::Type, @@ -729,11 +742,11 @@ impl<'hir> LoweringContext<'_, 'hir> { qself, path, ParamMode::ExplicitNamed, // no `'_` in declarations (Issue #61124) - ImplTraitContext::Disallowed(ImplTraitPosition::Path), + &ImplTraitContext::Disallowed(ImplTraitPosition::Path), ); self.arena.alloc(t) } else { - self.lower_ty(&f.ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)) + self.lower_ty(&f.ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)) }; let hir_id = self.lower_node_id(f.id); self.lower_attrs(hir_id, &f.attrs); @@ -756,14 +769,20 @@ impl<'hir> LoweringContext<'_, 'hir> { let (generics, kind, has_default) = match i.kind { AssocItemKind::Const(_, ref ty, ref default) => { - let ty = self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)); + let ty = self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)); let body = default.as_ref().map(|x| self.lower_const_body(i.span, Some(x))); (hir::Generics::empty(), hir::TraitItemKind::Const(ty, body), body.is_some()) } AssocItemKind::Fn(box Fn { ref sig, ref generics, body: None, .. }) => { + let asyncness = sig.header.asyncness; let names = self.lower_fn_params_to_names(&sig.decl); - let (generics, sig) = - self.lower_method_sig(generics, sig, i.id, FnDeclKind::Trait, None); + let (generics, sig) = self.lower_method_sig( + generics, + sig, + i.id, + FnDeclKind::Trait, + asyncness.opt_return_id(), + ); (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)), false) } AssocItemKind::Fn(box Fn { ref sig, ref generics, body: Some(ref body), .. }) => { @@ -791,15 +810,15 @@ impl<'hir> LoweringContext<'_, 'hir> { let (generics, kind) = self.lower_generics( &generics, i.id, - ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| { let ty = ty.as_ref().map(|x| { - this.lower_ty(x, ImplTraitContext::Disallowed(ImplTraitPosition::Type)) + this.lower_ty(x, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)) }); hir::TraitItemKind::Type( this.lower_param_bounds( bounds, - ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), ), ty, ) @@ -852,7 +871,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let (generics, kind) = match &i.kind { AssocItemKind::Const(_, ty, expr) => { - let ty = self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)); + let ty = self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)); ( hir::Generics::empty(), hir::ImplItemKind::Const(ty, self.lower_const_body(i.span, expr.as_deref())), @@ -879,14 +898,14 @@ impl<'hir> LoweringContext<'_, 'hir> { self.lower_generics( &generics, i.id, - ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| match ty { None => { let ty = this.arena.alloc(this.ty(i.span, hir::TyKind::Err)); hir::ImplItemKind::TyAlias(ty) } Some(ty) => { - let ty = this.lower_ty(ty, ImplTraitContext::TypeAliasesOpaqueTy); + let ty = this.lower_ty(ty, &ImplTraitContext::TypeAliasesOpaqueTy); hir::ImplItemKind::TyAlias(ty) } }, @@ -947,7 +966,11 @@ impl<'hir> LoweringContext<'_, 'hir> { params: &'hir [hir::Param<'hir>], value: hir::Expr<'hir>, ) -> hir::BodyId { - let body = hir::Body { generator_kind: self.generator_kind, params, value }; + let body = hir::Body { + generator_kind: self.generator_kind, + params, + value: self.arena.alloc(value), + }; let id = body.id(); debug_assert_eq!(id.hir_id.owner, self.current_hir_id_owner); self.bodies.push((id.hir_id.local_id, self.arena.alloc(body))); @@ -1074,12 +1097,9 @@ impl<'hir> LoweringContext<'_, 'hir> { // Check if this is a binding pattern, if so, we can optimize and avoid adding a // `let <pat> = __argN;` statement. In this case, we do not rename the parameter. let (ident, is_simple_parameter) = match parameter.pat.kind { - hir::PatKind::Binding( - hir::BindingAnnotation::Unannotated | hir::BindingAnnotation::Mutable, - _, - ident, - _, - ) => (ident, true), + hir::PatKind::Binding(hir::BindingAnnotation(ByRef::No, _), _, ident, _) => { + (ident, true) + } // For `ref mut` or wildcard arguments, we can't reuse the binding, but // we can keep the same name for the parameter. // This lets rustdoc render it correctly in documentation. @@ -1144,7 +1164,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let (move_pat, move_id) = this.pat_ident_binding_mode( desugared_span, ident, - hir::BindingAnnotation::Mutable, + hir::BindingAnnotation::MUT, ); let move_expr = this.expr_ident(desugared_span, ident, new_parameter_id); let move_stmt = this.stmt_let_pat( @@ -1225,12 +1245,12 @@ impl<'hir> LoweringContext<'_, 'hir> { sig: &FnSig, id: NodeId, kind: FnDeclKind, - is_async: Option<NodeId>, + is_async: Option<(NodeId, Span)>, ) -> (&'hir hir::Generics<'hir>, hir::FnSig<'hir>) { let header = self.lower_fn_header(sig.header); - let itctx = ImplTraitContext::Universal; - let (generics, decl) = self.lower_generics(generics, id, itctx, |this| { - this.lower_fn_decl(&sig.decl, Some(id), kind, is_async) + let mut itctx = ImplTraitContext::Universal; + let (generics, decl) = self.lower_generics(generics, id, &mut itctx, |this| { + this.lower_fn_decl(&sig.decl, Some(id), sig.span, kind, is_async) }); (generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) }) } @@ -1260,10 +1280,11 @@ impl<'hir> LoweringContext<'_, 'hir> { } fn error_on_invalid_abi(&self, abi: StrLit) { - struct_span_err!(self.tcx.sess, abi.span, E0703, "invalid ABI: found `{}`", abi.symbol) - .span_label(abi.span, "invalid ABI") - .help(&format!("valid ABIs: {}", abi::all_names().join(", "))) - .emit(); + self.tcx.sess.emit_err(InvalidAbi { + span: abi.span, + abi: abi.symbol, + valid_abis: abi::all_names().join(", "), + }); } fn lower_asyncness(&mut self, a: Async) -> hir::IsAsync { @@ -1294,7 +1315,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &mut self, generics: &Generics, parent_node_id: NodeId, - itctx: ImplTraitContext, + itctx: &ImplTraitContext, f: impl FnOnce(&mut Self) -> T, ) -> (&'hir hir::Generics<'hir>, T) { debug_assert!(self.impl_trait_defs.is_empty()); @@ -1338,11 +1359,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } let is_param = *is_param.get_or_insert_with(compute_is_param); if !is_param { - self.diagnostic().span_err( - bound.span(), - "`?Trait` bounds are only permitted at the \ - point where a type parameter is declared", - ); + self.tcx.sess.emit_err(MisplacedRelaxTraitBound { span: bound.span() }); } } } @@ -1403,7 +1420,7 @@ impl<'hir> LoweringContext<'_, 'hir> { id: NodeId, kind: &GenericParamKind, bounds: &[GenericBound], - itctx: ImplTraitContext, + itctx: &ImplTraitContext, origin: PredicateOrigin, ) -> Option<hir::WherePredicate<'hir>> { // Do not create a clause if we do not have anything inside it. @@ -1434,10 +1451,14 @@ impl<'hir> LoweringContext<'_, 'hir> { GenericParamKind::Const { .. } => None, GenericParamKind::Type { .. } => { let def_id = self.local_def_id(id).to_def_id(); + let hir_id = self.next_id(); + let res = Res::Def(DefKind::TyParam, def_id); let ty_path = self.arena.alloc(hir::Path { span: param_span, - res: Res::Def(DefKind::TyParam, def_id), - segments: self.arena.alloc_from_iter([hir::PathSegment::from_ident(ident)]), + res, + segments: self + .arena + .alloc_from_iter([hir::PathSegment::new(ident, hir_id, res)]), }); let ty_id = self.next_id(); let bounded_ty = @@ -1475,11 +1496,11 @@ impl<'hir> LoweringContext<'_, 'hir> { }) => hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate { bound_generic_params: self.lower_generic_params(bound_generic_params), bounded_ty: self - .lower_ty(bounded_ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)), + .lower_ty(bounded_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)), bounds: self.arena.alloc_from_iter(bounds.iter().map(|bound| { self.lower_param_bound( bound, - ImplTraitContext::Disallowed(ImplTraitPosition::Bound), + &ImplTraitContext::Disallowed(ImplTraitPosition::Bound), ) })), span: self.lower_span(span), @@ -1494,17 +1515,16 @@ impl<'hir> LoweringContext<'_, 'hir> { lifetime: self.lower_lifetime(lifetime), bounds: self.lower_param_bounds( bounds, - ImplTraitContext::Disallowed(ImplTraitPosition::Bound), + &ImplTraitContext::Disallowed(ImplTraitPosition::Bound), ), in_where_clause: true, }), - WherePredicate::EqPredicate(WhereEqPredicate { id, ref lhs_ty, ref rhs_ty, span }) => { + WherePredicate::EqPredicate(WhereEqPredicate { ref lhs_ty, ref rhs_ty, span }) => { hir::WherePredicate::EqPredicate(hir::WhereEqPredicate { - hir_id: self.lower_node_id(id), lhs_ty: self - .lower_ty(lhs_ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)), + .lower_ty(lhs_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)), rhs_ty: self - .lower_ty(rhs_ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)), + .lower_ty(rhs_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)), span: self.lower_span(span), }) } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 224dc3c23..9012aa704 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -32,14 +32,20 @@ #![feature(box_patterns)] #![feature(let_chains)] -#![feature(let_else)] +#![cfg_attr(bootstrap, feature(let_else))] #![feature(never_type)] #![recursion_limit = "256"] #![allow(rustc::potential_query_instability)] +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate tracing; +use crate::errors::{AssocTyParentheses, AssocTyParenthesesSub, MisplacedImplTrait, TraitFnAsync}; + +use rustc_arena::declare_arena; +use rustc_ast::ptr::P; use rustc_ast::visit; use rustc_ast::{self as ast, *}; use rustc_ast_pretty::pprust; @@ -49,7 +55,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sorted_map::SortedMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::Lrc; -use rustc_errors::{struct_span_err, Applicability, Handler}; +use rustc_errors::{DiagnosticArgFromDisplay, Handler, StashKey}; use rustc_hir as hir; use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res}; use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID}; @@ -75,6 +81,7 @@ macro_rules! arena_vec { mod asm; mod block; +mod errors; mod expr; mod index; mod item; @@ -89,6 +96,13 @@ struct LoweringContext<'a, 'hir> { /// Used to allocate HIR nodes. arena: &'hir hir::Arena<'hir>, + /// Used to allocate temporary AST nodes for use during lowering. + /// This allows us to create "fake" AST -- these nodes can sometimes + /// be allocated on the stack, but other times we need them to live longer + /// than the current stack frame, so they can be collected into vectors + /// and things like that. + ast_arena: &'a Arena<'static>, + /// Bodies inside the owner being lowered. bodies: Vec<(hir::ItemLocalId, &'hir hir::Body<'hir>)>, /// Attributes inside the owner being lowered. @@ -126,8 +140,23 @@ struct LoweringContext<'a, 'hir> { allow_try_trait: Option<Lrc<[Symbol]>>, allow_gen_future: Option<Lrc<[Symbol]>>, allow_into_future: Option<Lrc<[Symbol]>>, + + /// Mapping from generics `def_id`s to TAIT generics `def_id`s. + /// For each captured lifetime (e.g., 'a), we create a new lifetime parameter that is a generic + /// defined on the TAIT, so we have type Foo<'a1> = ... and we establish a mapping in this + /// field from the original parameter 'a to the new parameter 'a1. + generics_def_id_map: Vec<FxHashMap<LocalDefId, LocalDefId>>, } +declare_arena!([ + [] tys: rustc_ast::Ty, + [] aba: rustc_ast::AngleBracketedArgs, + [] ptr: rustc_ast::PolyTraitRef, + // This _marker field is needed because `declare_arena` creates `Arena<'tcx>` and we need to + // use `'tcx`. If we don't have this we get a compile error. + [] _marker: std::marker::PhantomData<&'tcx ()>, +]); + trait ResolverAstLoweringExt { fn legacy_const_generic_args(&self, expr: &Expr) -> Option<Vec<usize>>; fn get_partial_res(&self, id: NodeId) -> Option<PartialRes>; @@ -136,12 +165,6 @@ trait ResolverAstLoweringExt { fn get_lifetime_res(&self, id: NodeId) -> Option<LifetimeRes>; fn take_extra_lifetime_params(&mut self, id: NodeId) -> Vec<(Ident, NodeId, LifetimeRes)>; fn decl_macro_kind(&self, def_id: LocalDefId) -> MacroKind; - /// Record the map from `from` local def id to `to` local def id, on `generics_def_id_map` - /// field. - fn record_def_id_remap(&mut self, from: LocalDefId, to: LocalDefId); - /// Get the previously recorded `to` local def id given the `from` local def id, obtained using - /// `generics_def_id_map` field. - fn get_remapped_def_id(&self, local_def_id: LocalDefId) -> LocalDefId; } impl ResolverAstLoweringExt for ResolverAstLowering { @@ -209,41 +232,6 @@ impl ResolverAstLoweringExt for ResolverAstLowering { fn decl_macro_kind(&self, def_id: LocalDefId) -> MacroKind { self.builtin_macro_kinds.get(&def_id).copied().unwrap_or(MacroKind::Bang) } - - /// Push a remapping into the top-most map. - /// Panics if no map has been pushed. - /// Remapping is used when creating lowering `-> impl Trait` return - /// types to create the resulting opaque type. - #[tracing::instrument(level = "debug", skip(self))] - fn record_def_id_remap(&mut self, from: LocalDefId, to: LocalDefId) { - self.generics_def_id_map.last_mut().expect("no map pushed").insert(from, to); - } - - fn get_remapped_def_id(&self, mut local_def_id: LocalDefId) -> LocalDefId { - // `generics_def_id_map` is a stack of mappings. As we go deeper in impl traits nesting we - // push new mappings so we need to try first the latest mappings, hence `iter().rev()`. - // - // Consider: - // - // `fn test<'a, 'b>() -> impl Trait<&'a u8, Ty = impl Sized + 'b> {}` - // - // We would end with a generics_def_id_map like: - // - // `[[fn#'b -> impl_trait#'b], [fn#'b -> impl_sized#'b]]` - // - // for the opaque type generated on `impl Sized + 'b`, We want the result to be: - // impl_sized#'b, so iterating forward is the wrong thing to do. - for map in self.generics_def_id_map.iter().rev() { - if let Some(r) = map.get(&local_def_id) { - debug!("def_id_remapper: remapping from `{local_def_id:?}` to `{r:?}`"); - local_def_id = *r; - } else { - debug!("def_id_remapper: no remapping for `{local_def_id:?}` found in map"); - } - } - - local_def_id - } } /// Context of `impl Trait` in code, which determines whether it is allowed in an HIR subtree, @@ -264,6 +252,7 @@ enum ImplTraitContext { ReturnPositionOpaqueTy { /// Origin: Either OpaqueTyOrigin::FnReturn or OpaqueTyOrigin::AsyncFn, origin: hir::OpaqueTyOrigin, + in_trait: bool, }, /// Impl trait in type aliases. TypeAliasesOpaqueTy, @@ -323,7 +312,7 @@ impl std::fmt::Display for ImplTraitPosition { } } -#[derive(Debug)] +#[derive(Debug, PartialEq, Eq)] enum FnDeclKind { Fn, Inherent, @@ -335,9 +324,17 @@ enum FnDeclKind { } impl FnDeclKind { - fn impl_trait_return_allowed(&self) -> bool { + fn impl_trait_return_allowed(&self, tcx: TyCtxt<'_>) -> bool { match self { FnDeclKind::Fn | FnDeclKind::Inherent => true, + FnDeclKind::Impl if tcx.features().return_position_impl_trait_in_trait => true, + _ => false, + } + } + + fn impl_trait_in_trait_allowed(&self, tcx: TyCtxt<'_>) -> bool { + match self { + FnDeclKind::Trait if tcx.features().return_position_impl_trait_in_trait => true, _ => false, } } @@ -430,10 +427,13 @@ pub fn lower_to_hir<'hir>(tcx: TyCtxt<'hir>, (): ()) -> hir::Crate<'hir> { tcx.definitions_untracked().def_index_count(), ); + let ast_arena = Arena::default(); + for def_id in ast_index.indices() { item::ItemLowerer { tcx, resolver: &mut resolver, + ast_arena: &ast_arena, ast_index: &ast_index, owners: &mut owners, } @@ -500,6 +500,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } /// Given the id of some node in the AST, finds the `LocalDefId` associated with it by the name + /// resolver (if any). + fn orig_opt_local_def_id(&self, node: NodeId) -> Option<LocalDefId> { + self.resolver.node_id_to_def_id.get(&node).map(|local_def_id| *local_def_id) + } + + fn orig_local_def_id(&self, node: NodeId) -> LocalDefId { + self.orig_opt_local_def_id(node) + .unwrap_or_else(|| panic!("no entry for node id: `{:?}`", node)) + } + + /// Given the id of some node in the AST, finds the `LocalDefId` associated with it by the name /// resolver (if any), after applying any remapping from `get_remapped_def_id`. /// /// For example, in a function like `fn foo<'a>(x: &'a u32)`, @@ -513,16 +524,36 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { /// we would create an opaque type `type FooReturn<'a1> = impl Debug + 'a1`. /// When lowering the `Debug + 'a` bounds, we add a remapping to map `'a` to `'a1`. fn opt_local_def_id(&self, node: NodeId) -> Option<LocalDefId> { - self.resolver - .node_id_to_def_id - .get(&node) - .map(|local_def_id| self.resolver.get_remapped_def_id(*local_def_id)) + self.orig_opt_local_def_id(node).map(|local_def_id| self.get_remapped_def_id(local_def_id)) } fn local_def_id(&self, node: NodeId) -> LocalDefId { self.opt_local_def_id(node).unwrap_or_else(|| panic!("no entry for node id: `{:?}`", node)) } + /// Get the previously recorded `to` local def id given the `from` local def id, obtained using + /// `generics_def_id_map` field. + fn get_remapped_def_id(&self, local_def_id: LocalDefId) -> LocalDefId { + // `generics_def_id_map` is a stack of mappings. As we go deeper in impl traits nesting we + // push new mappings, so we first need to get the latest (innermost) mappings, hence `iter().rev()`. + // + // Consider: + // + // `fn test<'a, 'b>() -> impl Trait<&'a u8, Ty = impl Sized + 'b> {}` + // + // We would end with a generics_def_id_map like: + // + // `[[fn#'b -> impl_trait#'b], [fn#'b -> impl_sized#'b]]` + // + // for the opaque type generated on `impl Sized + 'b`, we want the result to be: impl_sized#'b. + // So, if we were trying to find first from the start (outermost) would give the wrong result, impl_trait#'b. + self.generics_def_id_map + .iter() + .rev() + .find_map(|map| map.get(&local_def_id).map(|local_def_id| *local_def_id)) + .unwrap_or(local_def_id) + } + /// Freshen the `LoweringContext` and ready it to lower a nested item. /// The lowered item is registered into `self.children`. /// @@ -591,9 +622,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { remap: FxHashMap<LocalDefId, LocalDefId>, f: impl FnOnce(&mut Self) -> R, ) -> R { - self.resolver.generics_def_id_map.push(remap); + self.generics_def_id_map.push(remap); let res = f(self); - self.resolver.generics_def_id_map.pop(); + self.generics_def_id_map.pop(); res } @@ -644,14 +675,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ) -> (Fingerprint, Fingerprint) { self.tcx.with_stable_hashing_context(|mut hcx| { let mut stable_hasher = StableHasher::new(); - hcx.with_hir_bodies(true, node.def_id(), bodies, |hcx| { + hcx.with_hir_bodies(node.def_id(), bodies, |hcx| { node.hash_stable(hcx, &mut stable_hasher) }); let hash_including_bodies = stable_hasher.finish(); let mut stable_hasher = StableHasher::new(); - hcx.with_hir_bodies(false, node.def_id(), bodies, |hcx| { - node.hash_stable(hcx, &mut stable_hasher) - }); + hcx.without_hir_bodies(|hcx| node.hash_stable(hcx, &mut stable_hasher)); let hash_without_bodies = stable_hasher.finish(); (hash_including_bodies, hash_without_bodies) }) @@ -663,6 +692,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { /// actually used in the HIR, as that would trigger an assertion in the /// `HirIdValidator` later on, which makes sure that all `NodeId`s got mapped /// properly. Calling the method twice with the same `NodeId` is fine though. + #[instrument(level = "debug", skip(self), ret)] fn lower_node_id(&mut self, ast_node_id: NodeId) -> hir::HirId { assert_ne!(ast_node_id, DUMMY_NODE_ID); @@ -696,6 +726,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } /// Generate a new `HirId` without a backing `NodeId`. + #[instrument(level = "debug", skip(self), ret)] fn next_id(&mut self) -> hir::HirId { let owner = self.current_hir_id_owner; let local_id = self.item_local_id_counter; @@ -767,7 +798,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } /// Converts a lifetime into a new generic parameter. - #[tracing::instrument(level = "debug", skip(self))] + #[instrument(level = "debug", skip(self))] fn lifetime_res_to_generic_param( &mut self, ident: Ident, @@ -811,7 +842,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { /// name resolver owing to lifetime elision; this also populates the resolver's node-id->def-id /// map, so that later calls to `opt_node_id_to_def_id` that refer to these extra lifetime /// parameters will be successful. - #[tracing::instrument(level = "debug", skip(self))] + #[instrument(level = "debug", skip(self))] #[inline] fn lower_lifetime_binder( &mut self, @@ -874,14 +905,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // the `HirId`s. We don't actually need HIR version of attributes anyway. // Tokens are also not needed after macro expansion and parsing. let kind = match attr.kind { - AttrKind::Normal(ref item, _) => AttrKind::Normal( - AttrItem { - path: item.path.clone(), - args: self.lower_mac_args(&item.args), + AttrKind::Normal(ref normal) => AttrKind::Normal(P(NormalAttr { + item: AttrItem { + path: normal.item.path.clone(), + args: self.lower_mac_args(&normal.item.args), tokens: None, }, - None, - ), + tokens: None, + })), AttrKind::DocComment(comment_kind, data) => AttrKind::DocComment(comment_kind, data), }; @@ -929,8 +960,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { lit.clone() } else { Lit { - token: token::Lit::new(token::LitKind::Err, kw::Empty, None), - kind: LitKind::Err(kw::Empty), + token_lit: token::Lit::new(token::LitKind::Err, kw::Empty, None), + kind: LitKind::Err, span: DUMMY_SP, } }; @@ -956,7 +987,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_assoc_ty_constraint( &mut self, constraint: &AssocConstraint, - itctx: ImplTraitContext, + itctx: &ImplTraitContext, ) -> hir::TypeBinding<'hir> { debug!("lower_assoc_ty_constraint(constraint={:?}, itctx={:?})", constraint, itctx); // lower generic arguments of identifier in constraint @@ -967,18 +998,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } GenericArgs::Parenthesized(ref data) => { self.emit_bad_parenthesized_trait_in_assoc_ty(data); - self.lower_angle_bracketed_parameter_data( - &data.as_angle_bracketed_args(), - ParamMode::Explicit, - itctx, - ) - .0 + let aba = self.ast_arena.aba.alloc(data.as_angle_bracketed_args()); + self.lower_angle_bracketed_parameter_data(aba, ParamMode::Explicit, itctx).0 } }; gen_args_ctor.into_generic_args(self) } else { self.arena.alloc(hir::GenericArgs::none()) }; + let itctx_tait = &ImplTraitContext::TypeAliasesOpaqueTy; let kind = match constraint.kind { AssocConstraintKind::Equality { ref term } => { @@ -1016,9 +1044,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // then to an opaque type). // // FIXME: this is only needed until `impl Trait` is allowed in type aliases. - ImplTraitContext::Disallowed(_) if self.is_in_dyn_type => { - (true, ImplTraitContext::TypeAliasesOpaqueTy) - } + ImplTraitContext::Disallowed(_) if self.is_in_dyn_type => (true, itctx_tait), // We are in the parameter position, but not within a dyn type: // @@ -1040,15 +1066,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.with_dyn_type_scope(false, |this| { let node_id = this.next_node_id(); - let ty = this.lower_ty( - &Ty { - id: node_id, - kind: TyKind::ImplTrait(impl_trait_node_id, bounds.clone()), - span: this.lower_span(constraint.span), - tokens: None, - }, - itctx, - ); + let ty = this.ast_arena.tys.alloc(Ty { + id: node_id, + kind: TyKind::ImplTrait(impl_trait_node_id, bounds.clone()), + span: this.lower_span(constraint.span), + tokens: None, + }); + let ty = this.lower_ty(ty, itctx); hir::TypeBindingKind::Equality { term: ty.into() } }) @@ -1072,19 +1096,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } fn emit_bad_parenthesized_trait_in_assoc_ty(&self, data: &ParenthesizedArgs) { - let mut err = self.tcx.sess.struct_span_err( - data.span, - "parenthesized generic arguments cannot be used in associated type constraints", - ); // Suggest removing empty parentheses: "Trait()" -> "Trait" - if data.inputs.is_empty() { + let sub = if data.inputs.is_empty() { let parentheses_span = data.inputs_span.shrink_to_lo().to(data.inputs_span.shrink_to_hi()); - err.multipart_suggestion( - "remove these parentheses", - vec![(parentheses_span, String::new())], - Applicability::MaybeIncorrect, - ); + AssocTyParenthesesSub::Empty { parentheses_span } } // Suggest replacing parentheses with angle brackets `Trait(params...)` to `Trait<params...>` else { @@ -1098,20 +1114,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // End of last argument to end of parameters let close_param = data.inputs.last().unwrap().span.shrink_to_hi().to(data.inputs_span.shrink_to_hi()); - err.multipart_suggestion( - &format!("use angle brackets instead",), - vec![(open_param, String::from("<")), (close_param, String::from(">"))], - Applicability::MaybeIncorrect, - ); - } - err.emit(); + AssocTyParenthesesSub::NotEmpty { open_param, close_param } + }; + self.tcx.sess.emit_err(AssocTyParentheses { span: data.span, sub }); } #[instrument(level = "debug", skip(self))] fn lower_generic_arg( &mut self, arg: &ast::GenericArg, - itctx: ImplTraitContext, + itctx: &ImplTraitContext, ) -> hir::GenericArg<'hir> { match arg { ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(<)), @@ -1163,7 +1175,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } _ => {} } - GenericArg::Type(self.lower_ty_direct(&ty, itctx)) + GenericArg::Type(self.lower_ty(&ty, itctx)) } ast::GenericArg::Const(ct) => GenericArg::Const(ConstArg { value: self.lower_anon_const(&ct), @@ -1173,7 +1185,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } #[instrument(level = "debug", skip(self))] - fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext) -> &'hir hir::Ty<'hir> { + fn lower_ty(&mut self, t: &Ty, itctx: &ImplTraitContext) -> &'hir hir::Ty<'hir> { self.arena.alloc(self.lower_ty_direct(t, itctx)) } @@ -1183,11 +1195,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { qself: &Option<QSelf>, path: &Path, param_mode: ParamMode, - itctx: ImplTraitContext, + itctx: &ImplTraitContext, ) -> hir::Ty<'hir> { // Check whether we should interpret this as a bare trait object. // This check mirrors the one in late resolution. We only introduce this special case in - // the rare occurence we need to lower `Fresh` anonymous lifetimes. + // the rare occurrence we need to lower `Fresh` anonymous lifetimes. // The other cases when a qpath should be opportunistically made a trait object are handled // by `ty_path`. if qself.is_none() @@ -1196,19 +1208,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { && let Res::Def(DefKind::Trait | DefKind::TraitAlias, _) = partial_res.base_res() { let (bounds, lifetime_bound) = self.with_dyn_type_scope(true, |this| { + let poly_trait_ref = this.ast_arena.ptr.alloc(PolyTraitRef { + bound_generic_params: vec![], + trait_ref: TraitRef { path: path.clone(), ref_id: t.id }, + span: t.span + }); let bound = this.lower_poly_trait_ref( - &PolyTraitRef { - bound_generic_params: vec![], - trait_ref: TraitRef { path: path.clone(), ref_id: t.id }, - span: t.span - }, + poly_trait_ref, itctx, ); let bounds = this.arena.alloc_from_iter([bound]); let lifetime_bound = this.elided_dyn_bound(t.span); (bounds, lifetime_bound) }); - let kind = hir::TyKind::TraitObject(bounds, lifetime_bound, TraitObjectSyntax::None); + let kind = hir::TyKind::TraitObject(bounds, &lifetime_bound, TraitObjectSyntax::None); return hir::Ty { kind, span: self.lower_span(t.span), hir_id: self.next_id() }; } @@ -1225,7 +1238,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.ty(span, hir::TyKind::Tup(tys)) } - fn lower_ty_direct(&mut self, t: &Ty, itctx: ImplTraitContext) -> hir::Ty<'hir> { + fn lower_ty_direct(&mut self, t: &Ty, itctx: &ImplTraitContext) -> hir::Ty<'hir> { let kind = match t.kind { TyKind::Infer => hir::TyKind::Infer, TyKind::Err => hir::TyKind::Err, @@ -1241,7 +1254,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } else { self.next_node_id() }; - let span = self.tcx.sess.source_map().next_point(t.span.shrink_to_lo()); + let span = self.tcx.sess.source_map().start_point(t.span); Lifetime { ident: Ident::new(kw::UnderscoreLifetime, span), id } }); let lifetime = self.lower_lifetime(®ion); @@ -1253,7 +1266,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { generic_params, unsafety: self.lower_unsafety(f.unsafety), abi: self.lower_extern(f.ext), - decl: self.lower_fn_decl(&f.decl, None, FnDeclKind::Pointer, None), + decl: self.lower_fn_decl(&f.decl, None, t.span, FnDeclKind::Pointer, None), param_names: self.lower_fn_params_to_names(&f.decl), })) } @@ -1268,14 +1281,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { return self.lower_path_ty(t, qself, path, ParamMode::Explicit, itctx); } TyKind::ImplicitSelf => { + let hir_id = self.next_id(); let res = self.expect_full_res(t.id); let res = self.lower_res(res); hir::TyKind::Path(hir::QPath::Resolved( None, self.arena.alloc(hir::Path { res, - segments: arena_vec![self; hir::PathSegment::from_ident( - Ident::with_dummy_span(kw::SelfUpper) + segments: arena_vec![self; hir::PathSegment::new( + Ident::with_dummy_span(kw::SelfUpper), + hir_id, + res )], span: self.lower_span(t.span), }), @@ -1318,19 +1334,23 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { TyKind::ImplTrait(def_node_id, ref bounds) => { let span = t.span; match itctx { - ImplTraitContext::ReturnPositionOpaqueTy { origin } => { - self.lower_opaque_impl_trait(span, origin, def_node_id, bounds, itctx) - } - ImplTraitContext::TypeAliasesOpaqueTy => { - let nested_itctx = ImplTraitContext::TypeAliasesOpaqueTy; - self.lower_opaque_impl_trait( + ImplTraitContext::ReturnPositionOpaqueTy { origin, in_trait } => self + .lower_opaque_impl_trait( span, - hir::OpaqueTyOrigin::TyAlias, + *origin, def_node_id, bounds, - nested_itctx, - ) - } + *in_trait, + itctx, + ), + ImplTraitContext::TypeAliasesOpaqueTy => self.lower_opaque_impl_trait( + span, + hir::OpaqueTyOrigin::TyAlias, + def_node_id, + bounds, + false, + &ImplTraitContext::TypeAliasesOpaqueTy, + ), ImplTraitContext::Universal => { let span = t.span; let ident = Ident::from_str_and_span(&pprust::ty_to_string(t), span); @@ -1342,15 +1362,26 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } path } + ImplTraitContext::Disallowed( + position @ (ImplTraitPosition::TraitReturn | ImplTraitPosition::ImplReturn), + ) => { + self.tcx + .sess + .create_feature_err( + MisplacedImplTrait { + span: t.span, + position: DiagnosticArgFromDisplay(&position), + }, + sym::return_position_impl_trait_in_trait, + ) + .emit(); + hir::TyKind::Err + } ImplTraitContext::Disallowed(position) => { - let mut err = struct_span_err!( - self.tcx.sess, - t.span, - E0562, - "`impl Trait` only allowed in function and inherent method return types, not in {}", - position - ); - err.emit(); + self.tcx.sess.emit_err(MisplacedImplTrait { + span: t.span, + position: DiagnosticArgFromDisplay(&position), + }); hir::TyKind::Err } } @@ -1397,14 +1428,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { /// added explicitly in the HIR). But this includes all the lifetimes, and we only want to /// capture the lifetimes that are referenced in the bounds. Therefore, we add *extra* lifetime parameters /// for the lifetimes that get captured (`'x`, in our example above) and reference those. - #[tracing::instrument(level = "debug", skip(self))] + #[instrument(level = "debug", skip(self), ret)] fn lower_opaque_impl_trait( &mut self, span: Span, origin: hir::OpaqueTyOrigin, opaque_ty_node_id: NodeId, bounds: &GenericBounds, - itctx: ImplTraitContext, + in_trait: bool, + itctx: &ImplTraitContext, ) -> hir::TyKind<'hir> { // Make sure we know that some funky desugaring has been going on here. // This is a first: there is code in other places like for loop @@ -1492,6 +1524,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }), bounds: hir_bounds, origin, + in_trait, }; debug!(?opaque_ty_item); @@ -1518,7 +1551,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { debug!(?lifetimes); // `impl Trait` now just becomes `Foo<'a, 'b, ..>`. - hir::TyKind::OpaqueDef(hir::ItemId { def_id: opaque_ty_def_id }, lifetimes) + hir::TyKind::OpaqueDef(hir::ItemId { def_id: opaque_ty_def_id }, lifetimes, in_trait) } /// Registers a new opaque type with the proper `NodeId`s and @@ -1577,7 +1610,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { LifetimeRes::Fresh { param, binder: _ } => { debug_assert_eq!(lifetime.ident.name, kw::UnderscoreLifetime); - if let Some(old_def_id) = self.opt_local_def_id(param) && remapping.get(&old_def_id).is_none() { + if let Some(old_def_id) = self.orig_opt_local_def_id(param) && remapping.get(&old_def_id).is_none() { let node_id = self.next_node_id(); let new_def_id = self.create_def( @@ -1626,19 +1659,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // `fn_def_id`: if `Some`, impl Trait arguments are lowered into generic parameters on the // given DefId, otherwise impl Trait is disallowed. Must be `Some` if // `make_ret_async` is also `Some`. - // `impl_trait_return_allow`: determines whether `impl Trait` can be used in return position. - // This guards against trait declarations and implementations where `impl Trait` is - // disallowed. // `make_ret_async`: if `Some`, converts `-> T` into `-> impl Future<Output = T>` in the // return type. This is used for `async fn` declarations. The `NodeId` is the ID of the - // return type `impl Trait` item. - #[tracing::instrument(level = "debug", skip(self))] + // return type `impl Trait` item, and the `Span` points to the `async` keyword. + #[instrument(level = "debug", skip(self))] fn lower_fn_decl( &mut self, decl: &FnDecl, fn_node_id: Option<NodeId>, + fn_span: Span, kind: FnDeclKind, - make_ret_async: Option<NodeId>, + make_ret_async: Option<(NodeId, Span)>, ) -> &'hir hir::FnDecl<'hir> { let c_variadic = decl.c_variadic(); @@ -1651,11 +1682,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } let inputs = self.arena.alloc_from_iter(inputs.iter().map(|param| { if fn_node_id.is_some() { - self.lower_ty_direct(¶m.ty, ImplTraitContext::Universal) + self.lower_ty_direct(¶m.ty, &ImplTraitContext::Universal) } else { self.lower_ty_direct( ¶m.ty, - ImplTraitContext::Disallowed(match kind { + &ImplTraitContext::Disallowed(match kind { FnDeclKind::Fn | FnDeclKind::Inherent => { unreachable!("fn should allow in-band lifetimes") } @@ -1669,20 +1700,63 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } })); - let output = if let Some(ret_id) = make_ret_async { - self.lower_async_fn_ret_ty( - &decl.output, - fn_node_id.expect("`make_ret_async` but no `fn_def_id`"), - ret_id, - ) + let output = if let Some((ret_id, span)) = make_ret_async { + match kind { + FnDeclKind::Trait => { + if !kind.impl_trait_in_trait_allowed(self.tcx) { + self.tcx + .sess + .create_feature_err( + TraitFnAsync { fn_span, span }, + sym::return_position_impl_trait_in_trait, + ) + .emit(); + } + self.lower_async_fn_ret_ty( + &decl.output, + fn_node_id.expect("`make_ret_async` but no `fn_def_id`"), + ret_id, + true, + ) + } + _ => { + if !kind.impl_trait_return_allowed(self.tcx) { + if kind == FnDeclKind::Impl { + self.tcx + .sess + .create_feature_err( + TraitFnAsync { fn_span, span }, + sym::return_position_impl_trait_in_trait, + ) + .emit(); + } else { + self.tcx.sess.emit_err(TraitFnAsync { fn_span, span }); + } + } + self.lower_async_fn_ret_ty( + &decl.output, + fn_node_id.expect("`make_ret_async` but no `fn_def_id`"), + ret_id, + false, + ) + } + } } else { match decl.output { FnRetTy::Ty(ref ty) => { - let context = match fn_node_id { - Some(fn_node_id) if kind.impl_trait_return_allowed() => { + let mut context = match fn_node_id { + Some(fn_node_id) if kind.impl_trait_return_allowed(self.tcx) => { + let fn_def_id = self.local_def_id(fn_node_id); + ImplTraitContext::ReturnPositionOpaqueTy { + origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), + in_trait: false, + } + } + Some(fn_node_id) if kind.impl_trait_in_trait_allowed(self.tcx) => { let fn_def_id = self.local_def_id(fn_node_id); ImplTraitContext::ReturnPositionOpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), + in_trait: true, } } _ => ImplTraitContext::Disallowed(match kind { @@ -1696,7 +1770,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { FnDeclKind::Impl => ImplTraitPosition::ImplReturn, }), }; - hir::FnRetTy::Return(self.lower_ty(ty, context)) + hir::FnRetTy::Return(self.lower_ty(ty, &mut context)) } FnRetTy::Default(span) => hir::FnRetTy::DefaultReturn(self.lower_span(span)), } @@ -1707,10 +1781,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { output, c_variadic, implicit_self: decl.inputs.get(0).map_or(hir::ImplicitSelfKind::None, |arg| { - use BindingMode::{ByRef, ByValue}; let is_mutable_pat = matches!( arg.pat.kind, - PatKind::Ident(ByValue(Mutability::Mut) | ByRef(Mutability::Mut), ..) + PatKind::Ident(hir::BindingAnnotation(_, Mutability::Mut), ..) ); match arg.ty.kind { @@ -1741,12 +1814,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // `output`: unlowered output type (`T` in `-> T`) // `fn_def_id`: `DefId` of the parent function (used to create child impl trait definition) // `opaque_ty_node_id`: `NodeId` of the opaque `impl Trait` type that should be created - #[tracing::instrument(level = "debug", skip(self))] + #[instrument(level = "debug", skip(self))] fn lower_async_fn_ret_ty( &mut self, output: &FnRetTy, fn_node_id: NodeId, opaque_ty_node_id: NodeId, + in_trait: bool, ) -> hir::FnRetTy<'hir> { let span = output.span(); @@ -1805,7 +1879,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let extra_lifetime_params = self.resolver.take_extra_lifetime_params(opaque_ty_node_id); debug!(?extra_lifetime_params); for (ident, outer_node_id, outer_res) in extra_lifetime_params { - let outer_def_id = self.local_def_id(outer_node_id); + let outer_def_id = self.orig_local_def_id(outer_node_id); let inner_node_id = self.next_node_id(); // Add a definition for the in scope lifetime def. @@ -1873,8 +1947,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // // Then, we will create `fn foo(..) -> Foo<'_, '_>`, and // hence the elision takes place at the fn site. - let future_bound = - this.lower_async_fn_output_type_to_future_bound(output, fn_def_id, span); + let future_bound = this.lower_async_fn_output_type_to_future_bound( + output, + span, + ImplTraitContext::ReturnPositionOpaqueTy { + origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), + in_trait, + }, + ); let generic_params = this.arena.alloc_from_iter(collected_lifetimes.iter().map( |&(new_node_id, lifetime, _)| { @@ -1912,6 +1992,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }), bounds: arena_vec![this; future_bound], origin: hir::OpaqueTyOrigin::AsyncFn(fn_def_id), + in_trait, }; trace!("exist ty from async fn def id: {:#?}", opaque_ty_def_id); @@ -1948,8 +2029,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let res = res.unwrap_or( self.resolver.get_lifetime_res(lifetime.id).unwrap_or(LifetimeRes::Error), ); - let l = self.new_named_lifetime_with_res(id, span, ident, res); - hir::GenericArg::Lifetime(l) + hir::GenericArg::Lifetime(self.new_named_lifetime_with_res(id, span, ident, res)) }, )); @@ -1957,8 +2037,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Foo = impl Trait` is, internally, created as a child of the // async fn, so the *type parameters* are inherited. It's // only the lifetime parameters that we must supply. - let opaque_ty_ref = - hir::TyKind::OpaqueDef(hir::ItemId { def_id: opaque_ty_def_id }, generic_args); + let opaque_ty_ref = hir::TyKind::OpaqueDef( + hir::ItemId { def_id: opaque_ty_def_id }, + generic_args, + in_trait, + ); let opaque_ty = self.ty(opaque_ty_span, opaque_ty_ref); hir::FnRetTy::Return(self.arena.alloc(opaque_ty)) } @@ -1967,8 +2050,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_async_fn_output_type_to_future_bound( &mut self, output: &FnRetTy, - fn_def_id: LocalDefId, span: Span, + mut nested_impl_trait_context: ImplTraitContext, ) -> hir::GenericBound<'hir> { // Compute the `T` in `Future<Output = T>` from the return type. let output_ty = match output { @@ -1976,10 +2059,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Not `OpaqueTyOrigin::AsyncFn`: that's only used for the // `impl Future` opaque type that `async fn` implicitly // generates. - let context = ImplTraitContext::ReturnPositionOpaqueTy { - origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), - }; - self.lower_ty(ty, context) + self.lower_ty(ty, &mut nested_impl_trait_context) } FnRetTy::Default(ret_ty_span) => self.arena.alloc(self.ty_tup(*ret_ty_span, &[])), }; @@ -2005,7 +2085,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_param_bound( &mut self, tpb: &GenericBound, - itctx: ImplTraitContext, + itctx: &ImplTraitContext, ) -> hir::GenericBound<'hir> { match tpb { GenericBound::Trait(p, modifier) => hir::GenericBound::Trait( @@ -2018,24 +2098,24 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } - fn lower_lifetime(&mut self, l: &Lifetime) -> hir::Lifetime { + fn lower_lifetime(&mut self, l: &Lifetime) -> &'hir hir::Lifetime { let span = self.lower_span(l.ident.span); let ident = self.lower_ident(l.ident); self.new_named_lifetime(l.id, l.id, span, ident) } - #[tracing::instrument(level = "debug", skip(self))] + #[instrument(level = "debug", skip(self))] fn new_named_lifetime_with_res( &mut self, id: NodeId, span: Span, ident: Ident, res: LifetimeRes, - ) -> hir::Lifetime { + ) -> &'hir hir::Lifetime { let name = match res { LifetimeRes::Param { param, .. } => { let p_name = ParamName::Plain(ident); - let param = self.resolver.get_remapped_def_id(param); + let param = self.get_remapped_def_id(param); hir::LifetimeName::Param(param, p_name) } @@ -2052,17 +2132,21 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }; debug!(?name); - hir::Lifetime { hir_id: self.lower_node_id(id), span: self.lower_span(span), name } + self.arena.alloc(hir::Lifetime { + hir_id: self.lower_node_id(id), + span: self.lower_span(span), + name, + }) } - #[tracing::instrument(level = "debug", skip(self))] + #[instrument(level = "debug", skip(self))] fn new_named_lifetime( &mut self, id: NodeId, new_id: NodeId, span: Span, ident: Ident, - ) -> hir::Lifetime { + ) -> &'hir hir::Lifetime { let res = self.resolver.get_lifetime_res(id).unwrap_or(LifetimeRes::Error); self.new_named_lifetime_with_res(new_id, span, ident, res) } @@ -2117,7 +2201,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { GenericParamKind::Type { ref default, .. } => { let kind = hir::GenericParamKind::Type { default: default.as_ref().map(|x| { - self.lower_ty(x, ImplTraitContext::Disallowed(ImplTraitPosition::Type)) + self.lower_ty(x, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)) }), synthetic: false, }; @@ -2125,7 +2209,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { (hir::ParamName::Plain(self.lower_ident(param.ident)), kind) } GenericParamKind::Const { ref ty, kw_span: _, ref default } => { - let ty = self.lower_ty(&ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)); + let ty = self.lower_ty(&ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)); let default = default.as_ref().map(|def| self.lower_anon_const(def)); ( hir::ParamName::Plain(self.lower_ident(param.ident)), @@ -2135,7 +2219,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } - fn lower_trait_ref(&mut self, p: &TraitRef, itctx: ImplTraitContext) -> hir::TraitRef<'hir> { + fn lower_trait_ref(&mut self, p: &TraitRef, itctx: &ImplTraitContext) -> hir::TraitRef<'hir> { let path = match self.lower_qpath(p.ref_id, &None, &p.path, ParamMode::Explicit, itctx) { hir::QPath::Resolved(None, path) => path, qpath => panic!("lower_trait_ref: unexpected QPath `{:?}`", qpath), @@ -2143,11 +2227,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::TraitRef { path, hir_ref_id: self.lower_node_id(p.ref_id) } } - #[tracing::instrument(level = "debug", skip(self))] + #[instrument(level = "debug", skip(self))] fn lower_poly_trait_ref( &mut self, p: &PolyTraitRef, - itctx: ImplTraitContext, + itctx: &ImplTraitContext, ) -> hir::PolyTraitRef<'hir> { let bound_generic_params = self.lower_lifetime_binder(p.trait_ref.ref_id, &p.bound_generic_params); @@ -2155,14 +2239,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::PolyTraitRef { bound_generic_params, trait_ref, span: self.lower_span(p.span) } } - fn lower_mt(&mut self, mt: &MutTy, itctx: ImplTraitContext) -> hir::MutTy<'hir> { + fn lower_mt(&mut self, mt: &MutTy, itctx: &ImplTraitContext) -> hir::MutTy<'hir> { hir::MutTy { ty: self.lower_ty(&mt.ty, itctx), mutbl: mt.mutbl } } + #[instrument(level = "debug", skip(self), ret)] fn lower_param_bounds( &mut self, bounds: &[GenericBound], - itctx: ImplTraitContext, + itctx: &ImplTraitContext, ) -> hir::GenericBounds<'hir> { self.arena.alloc_from_iter(self.lower_param_bounds_mut(bounds, itctx)) } @@ -2170,11 +2255,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_param_bounds_mut<'s>( &'s mut self, bounds: &'s [GenericBound], - itctx: ImplTraitContext, + itctx: &'s ImplTraitContext, ) -> impl Iterator<Item = hir::GenericBound<'hir>> + Captures<'s> + Captures<'a> { bounds.iter().map(move |bound| self.lower_param_bound(bound, itctx)) } + #[instrument(level = "debug", skip(self), ret)] fn lower_generic_and_bounds( &mut self, node_id: NodeId, @@ -2200,16 +2286,19 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { node_id, &GenericParamKind::Type { default: None }, bounds, - ImplTraitContext::Universal, + &ImplTraitContext::Universal, hir::PredicateOrigin::ImplTrait, ); + let hir_id = self.next_id(); + let res = Res::Def(DefKind::TyParam, def_id.to_def_id()); let ty = hir::TyKind::Path(hir::QPath::Resolved( None, self.arena.alloc(hir::Path { span: self.lower_span(span), - res: Res::Def(DefKind::TyParam, def_id.to_def_id()), - segments: arena_vec![self; hir::PathSegment::from_ident(self.lower_ident(ident))], + res, + segments: + arena_vec![self; hir::PathSegment::new(self.lower_ident(ident), hir_id, res)], }), )); @@ -2235,7 +2324,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { c.value.span, "using `_` for array lengths is unstable", ) - .emit(); + .stash(c.value.span, StashKey::UnderscoreForArrayLengths); hir::ArrayLen::Body(self.lower_anon_const(c)) } } @@ -2372,11 +2461,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } fn pat_ident(&mut self, span: Span, ident: Ident) -> (&'hir hir::Pat<'hir>, hir::HirId) { - self.pat_ident_binding_mode(span, ident, hir::BindingAnnotation::Unannotated) + self.pat_ident_binding_mode(span, ident, hir::BindingAnnotation::NONE) } fn pat_ident_mut(&mut self, span: Span, ident: Ident) -> (hir::Pat<'hir>, hir::HirId) { - self.pat_ident_binding_mode_mut(span, ident, hir::BindingAnnotation::Unannotated) + self.pat_ident_binding_mode_mut(span, ident, hir::BindingAnnotation::NONE) } fn pat_ident_binding_mode( @@ -2465,14 +2554,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { /// bound, like the bound in `Box<dyn Debug>`. This method is not invoked /// when the bound is written, even if it is written with `'_` like in /// `Box<dyn Debug + '_>`. In those cases, `lower_lifetime` is invoked. - fn elided_dyn_bound(&mut self, span: Span) -> hir::Lifetime { + fn elided_dyn_bound(&mut self, span: Span) -> &'hir hir::Lifetime { let r = hir::Lifetime { hir_id: self.next_id(), span: self.lower_span(span), name: hir::LifetimeName::ImplicitObjectLifetimeDefault, }; debug!("elided_dyn_bound: r={:?}", r); - r + self.arena.alloc(r) } } diff --git a/compiler/rustc_ast_lowering/src/lifetime_collector.rs b/compiler/rustc_ast_lowering/src/lifetime_collector.rs index 81006e00f..914fc5f58 100644 --- a/compiler/rustc_ast_lowering/src/lifetime_collector.rs +++ b/compiler/rustc_ast_lowering/src/lifetime_collector.rs @@ -1,9 +1,6 @@ use super::ResolverAstLoweringExt; use rustc_ast::visit::{self, BoundKind, LifetimeCtxt, Visitor}; -use rustc_ast::{ - FnRetTy, GenericBounds, Lifetime, NodeId, PathSegment, PolyTraitRef, TraitBoundModifier, Ty, - TyKind, -}; +use rustc_ast::{FnRetTy, GenericBounds, Lifetime, NodeId, PathSegment, PolyTraitRef, Ty, TyKind}; use rustc_hir::def::LifetimeRes; use rustc_middle::span_bug; use rustc_middle::ty::ResolverAstLowering; @@ -66,15 +63,15 @@ impl<'ast> Visitor<'ast> for LifetimeCollectVisitor<'ast> { self.record_lifetime_use(*lifetime); } - fn visit_path_segment(&mut self, path_span: Span, path_segment: &'ast PathSegment) { - self.record_elided_anchor(path_segment.id, path_span); - visit::walk_path_segment(self, path_span, path_segment); + fn visit_path_segment(&mut self, path_segment: &'ast PathSegment) { + self.record_elided_anchor(path_segment.id, path_segment.ident.span); + visit::walk_path_segment(self, path_segment); } - fn visit_poly_trait_ref(&mut self, t: &'ast PolyTraitRef, m: &'ast TraitBoundModifier) { + fn visit_poly_trait_ref(&mut self, t: &'ast PolyTraitRef) { self.current_binders.push(t.trait_ref.ref_id); - visit::walk_poly_trait_ref(self, t, m); + visit::walk_poly_trait_ref(self, t); self.current_binders.pop(); } diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index bd2e76e55..1ea76fdbf 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -1,3 +1,6 @@ +use super::errors::{ + ArbitraryExpressionInPattern, ExtraDoubleDot, MisplacedDoubleDot, SubTupleBinding, +}; use super::ResolverAstLoweringExt; use super::{ImplTraitContext, LoweringContext, ParamMode}; use crate::ImplTraitPosition; @@ -5,7 +8,6 @@ use crate::ImplTraitPosition; use rustc_ast::ptr::P; use rustc_ast::*; use rustc_data_structures::stack::ensure_sufficient_stack; -use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::def::Res; use rustc_span::symbol::Ident; @@ -22,7 +24,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let node = loop { match pattern.kind { PatKind::Wild => break hir::PatKind::Wild, - PatKind::Ident(ref binding_mode, ident, ref sub) => { + PatKind::Ident(binding_mode, ident, ref sub) => { let lower_sub = |this: &mut Self| sub.as_ref().map(|s| this.lower_pat(&*s)); break self.lower_pat_ident(pattern, binding_mode, ident, lower_sub); } @@ -35,7 +37,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { qself, path, ParamMode::Optional, - ImplTraitContext::Disallowed(ImplTraitPosition::Path), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Path), ); let (pats, ddpos) = self.lower_pat_tuple(pats, "tuple struct"); break hir::PatKind::TupleStruct(qpath, pats, ddpos); @@ -51,7 +53,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { qself, path, ParamMode::Optional, - ImplTraitContext::Disallowed(ImplTraitPosition::Path), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Path), ); break hir::PatKind::Path(qpath); } @@ -61,15 +63,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { qself, path, ParamMode::Optional, - ImplTraitContext::Disallowed(ImplTraitPosition::Path), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Path), ); - let fs = self.arena.alloc_from_iter(fields.iter().map(|f| hir::PatField { - hir_id: self.next_id(), - ident: self.lower_ident(f.ident), - pat: self.lower_pat(&f.pat), - is_shorthand: f.is_shorthand, - span: self.lower_span(f.span), + let fs = self.arena.alloc_from_iter(fields.iter().map(|f| { + let hir_id = self.lower_node_id(f.id); + self.lower_attrs(hir_id, &f.attrs); + + hir::PatField { + hir_id, + ident: self.lower_ident(f.ident), + pat: self.lower_pat(&f.pat), + is_shorthand: f.is_shorthand, + span: self.lower_span(f.span), + } })); break hir::PatKind::Struct(qpath, fs, etc); } @@ -109,7 +116,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &mut self, pats: &[P<Pat>], ctx: &str, - ) -> (&'hir [hir::Pat<'hir>], Option<usize>) { + ) -> (&'hir [hir::Pat<'hir>], hir::DotDotPos) { let mut elems = Vec::with_capacity(pats.len()); let mut rest = None; @@ -129,20 +136,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // This is not allowed as a sub-tuple pattern PatKind::Ident(ref _bm, ident, Some(ref sub)) if sub.is_rest() => { let sp = pat.span; - self.diagnostic() - .struct_span_err( - sp, - &format!("`{} @` is not allowed in a {}", ident.name, ctx), - ) - .span_label(sp, "this is only allowed in slice patterns") - .help("remove this and bind each tuple field independently") - .span_suggestion_verbose( - sp, - &format!("if you don't need to use the contents of {}, discard the tuple's remaining fields", ident), - "..", - Applicability::MaybeIncorrect, - ) - .emit(); + self.tcx.sess.emit_err(SubTupleBinding { + span: sp, + ident_name: ident.name, + ident, + ctx, + }); } _ => {} } @@ -161,7 +160,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } - (self.arena.alloc_from_iter(elems), rest.map(|(ddpos, _)| ddpos)) + (self.arena.alloc_from_iter(elems), hir::DotDotPos::new(rest.map(|(ddpos, _)| ddpos))) } /// Lower a slice pattern of form `[pat_0, ..., pat_n]` into @@ -177,9 +176,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let mut prev_rest_span = None; // Lowers `$bm $ident @ ..` to `$bm $ident @ _`. - let lower_rest_sub = |this: &mut Self, pat, bm, ident, sub| { + let lower_rest_sub = |this: &mut Self, pat, ann, ident, sub| { let lower_sub = |this: &mut Self| Some(this.pat_wild_with_node_id_of(sub)); - let node = this.lower_pat_ident(pat, bm, ident, lower_sub); + let node = this.lower_pat_ident(pat, ann, ident, lower_sub); this.pat_with_node_id_of(pat, node) }; @@ -195,9 +194,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } // Found a sub-slice pattern `$binding_mode $ident @ ..`. // Record, lower it to `$binding_mode $ident @ _`, and stop here. - PatKind::Ident(ref bm, ident, Some(ref sub)) if sub.is_rest() => { + PatKind::Ident(ann, ident, Some(ref sub)) if sub.is_rest() => { prev_rest_span = Some(sub.span); - slice = Some(self.arena.alloc(lower_rest_sub(self, pat, bm, ident, sub))); + slice = Some(self.arena.alloc(lower_rest_sub(self, pat, ann, ident, sub))); break; } // It was not a subslice pattern so lower it normally. @@ -210,9 +209,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // There was a previous subslice pattern; make sure we don't allow more. let rest_span = match pat.kind { PatKind::Rest => Some(pat.span), - PatKind::Ident(ref bm, ident, Some(ref sub)) if sub.is_rest() => { + PatKind::Ident(ann, ident, Some(ref sub)) if sub.is_rest() => { // #69103: Lower into `binding @ _` as above to avoid ICEs. - after.push(lower_rest_sub(self, pat, bm, ident, sub)); + after.push(lower_rest_sub(self, pat, ann, ident, sub)); Some(sub.span) } _ => None, @@ -236,7 +235,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_pat_ident( &mut self, p: &Pat, - binding_mode: &BindingMode, + annotation: BindingAnnotation, ident: Ident, lower_sub: impl FnOnce(&mut Self) -> Option<&'hir hir::Pat<'hir>>, ) -> hir::PatKind<'hir> { @@ -249,29 +248,24 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }; hir::PatKind::Binding( - self.lower_binding_mode(binding_mode), + annotation, self.lower_node_id(canonical_id), self.lower_ident(ident), lower_sub(self), ) } - Some(res) => hir::PatKind::Path(hir::QPath::Resolved( - None, - self.arena.alloc(hir::Path { - span: self.lower_span(ident.span), - res: self.lower_res(res), - segments: arena_vec![self; hir::PathSegment::from_ident(self.lower_ident(ident))], - }), - )), - } - } - - fn lower_binding_mode(&mut self, b: &BindingMode) -> hir::BindingAnnotation { - match *b { - BindingMode::ByValue(Mutability::Not) => hir::BindingAnnotation::Unannotated, - BindingMode::ByRef(Mutability::Not) => hir::BindingAnnotation::Ref, - BindingMode::ByValue(Mutability::Mut) => hir::BindingAnnotation::Mutable, - BindingMode::ByRef(Mutability::Mut) => hir::BindingAnnotation::RefMut, + Some(res) => { + let hir_id = self.next_id(); + let res = self.lower_res(res); + hir::PatKind::Path(hir::QPath::Resolved( + None, + self.arena.alloc(hir::Path { + span: self.lower_span(ident.span), + res, + segments: arena_vec![self; hir::PathSegment::new(self.lower_ident(ident), hir_id, res)], + }), + )) + } } } @@ -291,19 +285,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { /// Emit a friendly error for extra `..` patterns in a tuple/tuple struct/slice pattern. pub(crate) fn ban_extra_rest_pat(&self, sp: Span, prev_sp: Span, ctx: &str) { - self.diagnostic() - .struct_span_err(sp, &format!("`..` can only be used once per {} pattern", ctx)) - .span_label(sp, &format!("can only be used once per {} pattern", ctx)) - .span_label(prev_sp, "previously used here") - .emit(); + self.tcx.sess.emit_err(ExtraDoubleDot { span: sp, prev_span: prev_sp, ctx }); } /// Used to ban the `..` pattern in places it shouldn't be semantically. fn ban_illegal_rest_pat(&self, sp: Span) -> hir::PatKind<'hir> { - self.diagnostic() - .struct_span_err(sp, "`..` patterns are not allowed here") - .note("only allowed in tuple, tuple struct, and slice patterns") - .emit(); + self.tcx.sess.emit_err(MisplacedDoubleDot { span: sp }); // We're not in a list context so `..` can be reasonably treated // as `_` because it should always be valid and roughly matches the @@ -340,8 +327,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ExprKind::Path(..) if allow_paths => {} ExprKind::Unary(UnOp::Neg, ref inner) if matches!(inner.kind, ExprKind::Lit(_)) => {} _ => { - self.diagnostic() - .span_err(expr.span, "arbitrary expressions aren't allowed in patterns"); + self.tcx.sess.emit_err(ArbitraryExpressionInPattern { span: expr.span }); return self.arena.alloc(self.expr_err(expr.span)); } } diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index 393be3b45..6bb1bb9ea 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -1,11 +1,11 @@ use crate::ImplTraitPosition; +use super::errors::{GenericTypeWithParentheses, UseAngleBrackets}; use super::ResolverAstLoweringExt; use super::{GenericArgsCtor, LifetimeRes, ParenthesizedGenericArgs}; use super::{ImplTraitContext, LoweringContext, ParamMode}; use rustc_ast::{self as ast, *}; -use rustc_errors::{struct_span_err, Applicability}; use rustc_hir as hir; use rustc_hir::def::{DefKind, PartialRes, Res}; use rustc_hir::GenericArg; @@ -13,7 +13,6 @@ use rustc_span::symbol::{kw, Ident}; use rustc_span::{BytePos, Span, DUMMY_SP}; use smallvec::smallvec; -use tracing::debug; impl<'a, 'hir> LoweringContext<'a, 'hir> { #[instrument(level = "trace", skip(self))] @@ -23,7 +22,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { qself: &Option<QSelf>, p: &Path, param_mode: ParamMode, - itctx: ImplTraitContext, + itctx: &ImplTraitContext, ) -> hir::QPath<'hir> { let qself_position = qself.as_ref().map(|q| q.position); let qself = qself.as_ref().map(|q| self.lower_ty(&q.ty, itctx)); @@ -157,7 +156,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { segment, param_mode, ParenthesizedGenericArgs::Err, - ImplTraitContext::Disallowed(ImplTraitPosition::Path), + &ImplTraitContext::Disallowed(ImplTraitPosition::Path), ) })), span: self.lower_span(p.span), @@ -181,11 +180,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { segment: &PathSegment, param_mode: ParamMode, parenthesized_generic_args: ParenthesizedGenericArgs, - itctx: ImplTraitContext, + itctx: &ImplTraitContext, ) -> hir::PathSegment<'hir> { debug!("path_span: {:?}, lower_path_segment(segment: {:?})", path_span, segment,); let (mut generic_args, infer_args) = if let Some(ref generic_args) = segment.args { - let msg = "parenthesized type parameters may only be used with a `Fn` trait"; match **generic_args { GenericArgs::AngleBracketed(ref data) => { self.lower_angle_bracketed_parameter_data(data, param_mode, itctx) @@ -193,10 +191,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { GenericArgs::Parenthesized(ref data) => match parenthesized_generic_args { ParenthesizedGenericArgs::Ok => self.lower_parenthesized_parameter_data(data), ParenthesizedGenericArgs::Err => { - let mut err = struct_span_err!(self.tcx.sess, data.span, E0214, "{}", msg); - err.span_label(data.span, "only `Fn` traits may use parentheses"); // Suggest replacing parentheses with angle brackets `Trait(params...)` to `Trait<params...>` - if !data.inputs.is_empty() { + let sub = if !data.inputs.is_empty() { // Start of the span to the 1st character of 1st argument let open_param = data.inputs_span.shrink_to_lo().to(data .inputs @@ -212,16 +208,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { .span .shrink_to_hi() .to(data.inputs_span.shrink_to_hi()); - err.multipart_suggestion( - &format!("use angle brackets instead",), - vec![ - (open_param, String::from("<")), - (close_param, String::from(">")), - ], - Applicability::MaybeIncorrect, - ); - } - err.emit(); + + Some(UseAngleBrackets { open_param, close_param }) + } else { + None + }; + self.tcx.sess.emit_err(GenericTypeWithParentheses { span: data.span, sub }); ( self.lower_angle_bracketed_parameter_data( &data.as_angle_bracketed_args(), @@ -258,16 +250,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } let res = self.expect_full_res(segment.id); - let id = self.lower_node_id(segment.id); + let hir_id = self.lower_node_id(segment.id); debug!( "lower_path_segment: ident={:?} original-id={:?} new-id={:?}", - segment.ident, segment.id, id, + segment.ident, segment.id, hir_id, ); hir::PathSegment { ident: self.lower_ident(segment.ident), - hir_id: Some(id), - res: Some(self.lower_res(res)), + hir_id, + res: self.lower_res(res), infer_args, args: if generic_args.is_empty() && generic_args.span.is_empty() { None @@ -324,7 +316,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &mut self, data: &AngleBracketedArgs, param_mode: ParamMode, - itctx: ImplTraitContext, + itctx: &ImplTraitContext, ) -> (GenericArgsCtor<'hir>, bool) { let has_non_lt_args = data.args.iter().any(|arg| match arg { AngleBracketedArg::Arg(ast::GenericArg::Lifetime(_)) @@ -358,15 +350,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // we generally don't permit such things (see #51008). let ParenthesizedArgs { span, inputs, inputs_span, output } = data; let inputs = self.arena.alloc_from_iter(inputs.iter().map(|ty| { - self.lower_ty_direct(ty, ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitParam)) + self.lower_ty_direct(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitParam)) })); let output_ty = match output { FnRetTy::Ty(ty) => { - self.lower_ty(&ty, ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitReturn)) + self.lower_ty(&ty, &ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitReturn)) } FnRetTy::Default(_) => self.arena.alloc(self.ty_tup(*span, &[])), }; - let args = smallvec![GenericArg::Type(self.ty_tup(*inputs_span, inputs))]; + let args = smallvec![GenericArg::Type(self.arena.alloc(self.ty_tup(*inputs_span, inputs)))]; let binding = self.output_ty_binding(output_ty.span, output_ty); ( GenericArgsCtor { |