From 413ca98d9110404d745471e54af10fc950292417 Mon Sep 17 00:00:00 2001 From: Eugene Talagrand Date: Sat, 16 Oct 2021 18:23:42 -1000 Subject: [PATCH 01/20] Update std::env::temp_dir to use GetTempPath2 on Windows when available. As a security measure, Windows 11 introduces a new temporary directory API, GetTempPath2. When the calling process is running as SYSTEM, a separate temporary directory will be returned inaccessible to non-SYSTEM processes. For non-SYSTEM processes the behavior will be the same as before. --- library/std/src/env.rs | 21 +++++++++------------ library/std/src/sys/windows/c.rs | 6 ++++++ library/std/src/sys/windows/os.rs | 2 +- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/library/std/src/env.rs b/library/std/src/env.rs index 40b46878cd8ba..6b5801850933e 100644 --- a/library/std/src/env.rs +++ b/library/std/src/env.rs @@ -578,28 +578,25 @@ pub fn home_dir() -> Option { /// may result in "insecure temporary file" security vulnerabilities. Consider /// using a crate that securely creates temporary files or directories. /// -/// # Unix +/// # Platform-specific behavior /// -/// Returns the value of the `TMPDIR` environment variable if it is +/// On Unix, returns the value of the `TMPDIR` environment variable if it is /// set, otherwise for non-Android it returns `/tmp`. If Android, since there /// is no global temporary folder (it is usually allocated per-app), it returns /// `/data/local/tmp`. +/// On Windows, the behavior is equivalent to that of [`GetTempPath2`][GetTempPath2] / +/// [`GetTempPath`][GetTempPath], which this function uses internally. +/// Note that, this [may change in the future][changes]. /// -/// # Windows -/// -/// Returns the value of, in order, the `TMP`, `TEMP`, -/// `USERPROFILE` environment variable if any are set and not the empty -/// string. Otherwise, `temp_dir` returns the path of the Windows directory. -/// This behavior is identical to that of [`GetTempPath`][msdn], which this -/// function uses internally. -/// -/// [msdn]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettemppatha +/// [changes]: io#platform-specific-behavior +/// [GetTempPath2]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettemppath2a +/// [GetTempPath]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettemppatha /// /// ```no_run /// use std::env; /// /// fn main() { -/// let mut dir = env::temp_dir(); +/// let dir = env::temp_dir(); /// println!("Temporary directory: {}", dir.display()); /// } /// ``` diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs index e5c550802a7ab..87add8b08749b 100644 --- a/library/std/src/sys/windows/c.rs +++ b/library/std/src/sys/windows/c.rs @@ -1102,6 +1102,12 @@ compat_fn! { -> () { GetSystemTimeAsFileTime(lpSystemTimeAsFileTime) } + + // >= Win11 + // https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettemppath2a + pub fn GetTempPath2W(nBufferLength: DWORD, lpBuffer: LPCWSTR) -> DWORD { + GetTempPathW(nBufferLength, lpBuffer) + } } compat_fn! { diff --git a/library/std/src/sys/windows/os.rs b/library/std/src/sys/windows/os.rs index 883690c483167..0c26321c47d08 100644 --- a/library/std/src/sys/windows/os.rs +++ b/library/std/src/sys/windows/os.rs @@ -275,7 +275,7 @@ pub fn unsetenv(n: &OsStr) -> io::Result<()> { } pub fn temp_dir() -> PathBuf { - super::fill_utf16_buf(|buf, sz| unsafe { c::GetTempPathW(sz, buf) }, super::os2path).unwrap() + super::fill_utf16_buf(|buf, sz| unsafe { c::GetTempPath2W(sz, buf) }, super::os2path).unwrap() } #[cfg(not(target_vendor = "uwp"))] From 1d26e413de7a026ae2e99dad82edd2b8affcf5f3 Mon Sep 17 00:00:00 2001 From: Eugene Talagrand Date: Tue, 26 Oct 2021 17:49:55 -0700 Subject: [PATCH 02/20] Clarify platform availability of GetTempPath2 Windows Server 2022 is a different version from Win11, breaking precent --- library/std/src/sys/windows/c.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs index 87add8b08749b..b9f49fed76957 100644 --- a/library/std/src/sys/windows/c.rs +++ b/library/std/src/sys/windows/c.rs @@ -1103,7 +1103,7 @@ compat_fn! { GetSystemTimeAsFileTime(lpSystemTimeAsFileTime) } - // >= Win11 + // >= Win11 / Server 2022 // https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettemppath2a pub fn GetTempPath2W(nBufferLength: DWORD, lpBuffer: LPCWSTR) -> DWORD { GetTempPathW(nBufferLength, lpBuffer) From 70855b24b89e348aef0e28a0fe6db6d5bf19d11e Mon Sep 17 00:00:00 2001 From: luojia65 Date: Sun, 5 Dec 2021 16:32:14 +0800 Subject: [PATCH 03/20] Add spin_loop hint for RISC-V architecture This commit also updates `stdarch` git submodule. --- library/core/src/hint.rs | 5 +++++ library/stdarch | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs index 95798879155c5..f49aefea81bac 100644 --- a/library/core/src/hint.rs +++ b/library/core/src/hint.rs @@ -137,6 +137,11 @@ pub fn spin_loop() { unsafe { crate::arch::arm::__yield() }; } } + + #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] + { + crate::arch::riscv::pause(); + } } /// An identity function that *__hints__* to the compiler to be maximally pessimistic about what diff --git a/library/stdarch b/library/stdarch index cfba59fccd90b..43b4556c44197 160000 --- a/library/stdarch +++ b/library/stdarch @@ -1 +1 @@ -Subproject commit cfba59fccd90b3b52a614120834320f764ab08d1 +Subproject commit 43b4556c44197af4ef82e42a12dfc513a1397f87 From 61cab770bd55fdc3d9d6ac86a9e0ccf7ddbb3f51 Mon Sep 17 00:00:00 2001 From: b-naber Date: Sun, 5 Dec 2021 11:13:51 +0100 Subject: [PATCH 04/20] allow for failure of subst_normalize_erasing_regions in const_eval --- .../src/interpret/eval_context.rs | 23 +++++++++++----- .../rustc_const_eval/src/interpret/operand.rs | 4 +-- .../rustc_const_eval/src/interpret/place.rs | 2 +- .../rustc_const_eval/src/interpret/step.rs | 5 ++-- compiler/rustc_middle/src/ty/instance.rs | 18 +++++++++++++ .../src/ty/normalize_erasing_regions.rs | 26 +++++++++++++++++++ 6 files changed, 67 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index cf084faade8cc..d46950ed90315 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -7,6 +7,7 @@ use rustc_hir::{self as hir, def_id::DefId, definitions::DefPathData}; use rustc_index::vec::IndexVec; use rustc_macros::HashStable; use rustc_middle::mir; +use rustc_middle::mir::interpret::{InterpError, InvalidProgramInfo}; use rustc_middle::ty::layout::{self, LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout}; use rustc_middle::ty::{ self, query::TyCtxtAt, subst::SubstsRef, ParamEnv, Ty, TyCtxt, TypeFoldable, @@ -14,7 +15,7 @@ use rustc_middle::ty::{ use rustc_mir_dataflow::storage::AlwaysLiveLocals; use rustc_query_system::ich::StableHashingContext; use rustc_session::Limit; -use rustc_span::{Pos, Span}; +use rustc_span::{Pos, Span, DUMMY_SP}; use rustc_target::abi::{Align, HasDataLayout, Size, TargetDataLayout}; use super::{ @@ -508,7 +509,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { pub(super) fn subst_from_current_frame_and_normalize_erasing_regions>( &self, value: T, - ) -> T { + ) -> Result> { self.subst_from_frame_and_normalize_erasing_regions(self.frame(), value) } @@ -518,8 +519,18 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { &self, frame: &Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra>, value: T, - ) -> T { - frame.instance.subst_mir_and_normalize_erasing_regions(*self.tcx, self.param_env, value) + ) -> Result> { + frame + .instance + .try_subst_mir_and_normalize_erasing_regions(*self.tcx, self.param_env, value) + .or_else(|e| { + self.tcx.sess.delay_span_bug( + DUMMY_SP, + format!("failed to normalize {}", e.get_type_for_failure()).as_str(), + ); + + Err(InterpError::InvalidProgram(InvalidProgramInfo::TooGeneric)) + }) } /// The `substs` are assumed to already be in our interpreter "universe" (param_env). @@ -554,7 +565,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let layout = from_known_layout(self.tcx, self.param_env, layout, || { let local_ty = frame.body.local_decls[local].ty; let local_ty = - self.subst_from_frame_and_normalize_erasing_regions(frame, local_ty); + self.subst_from_frame_and_normalize_erasing_regions(frame, local_ty)?; self.layout_of(local_ty) })?; if let Some(state) = frame.locals.get(local) { @@ -702,7 +713,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { for const_ in &body.required_consts { let span = const_.span; let const_ = - self.subst_from_current_frame_and_normalize_erasing_regions(const_.literal); + self.subst_from_current_frame_and_normalize_erasing_regions(const_.literal)?; self.mir_const_to_op(&const_, None).map_err(|err| { // If there was an error, set the span of the current frame to this constant. // Avoiding doing this when evaluation succeeds. diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index de9e94ce2ac0c..e82ce73c814ff 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -512,7 +512,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.param_env, self.layout_of(self.subst_from_current_frame_and_normalize_erasing_regions( place.ty(&self.frame().body.local_decls, *self.tcx).ty - ))?, + )?)?, op.layout, )); Ok(op) @@ -534,7 +534,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Constant(ref constant) => { let val = - self.subst_from_current_frame_and_normalize_erasing_regions(constant.literal); + self.subst_from_current_frame_and_normalize_erasing_regions(constant.literal)?; // This can still fail: // * During ConstProp, with `TooGeneric` or since the `requried_consts` were not all // checked yet. diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index d7f2853fc86f5..4c95da896a223 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -643,7 +643,7 @@ where self.param_env, self.layout_of(self.subst_from_current_frame_and_normalize_erasing_regions( place.ty(&self.frame().body.local_decls, *self.tcx).ty - ))?, + )?)?, place_ty.layout, )); Ok(place_ty) diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index 9299ae2b2b9f8..992cef1cb6aa0 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -276,7 +276,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } NullaryOp(null_op, ty) => { - let ty = self.subst_from_current_frame_and_normalize_erasing_regions(ty); + let ty = self.subst_from_current_frame_and_normalize_erasing_regions(ty)?; let layout = self.layout_of(ty)?; if layout.is_unsized() { // FIXME: This should be a span_bug (#80742) @@ -302,7 +302,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Cast(cast_kind, ref operand, cast_ty) => { let src = self.eval_operand(operand, None)?; - let cast_ty = self.subst_from_current_frame_and_normalize_erasing_regions(cast_ty); + let cast_ty = + self.subst_from_current_frame_and_normalize_erasing_regions(cast_ty)?; self.cast(&src, cast_kind, cast_ty, &dest)?; } diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 4b38105e44717..2d30126273064 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -7,6 +7,7 @@ use rustc_hir::def::Namespace; use rustc_hir::def_id::{CrateNum, DefId}; use rustc_hir::lang_items::LangItem; use rustc_macros::HashStable; +use rustc_middle::ty::normalize_erasing_regions::NormalizationError; use std::fmt; @@ -575,6 +576,23 @@ impl<'tcx> Instance<'tcx> { } } + #[inline(always)] + pub fn try_subst_mir_and_normalize_erasing_regions( + &self, + tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + v: T, + ) -> Result> + where + T: TypeFoldable<'tcx> + Clone, + { + if let Some(substs) = self.substs_for_mir_body() { + tcx.try_subst_and_normalize_erasing_regions(substs, param_env, v) + } else { + tcx.try_normalize_erasing_regions(param_env, v) + } + } + /// Returns a new `Instance` where generic parameters in `instance.substs` are replaced by /// identity parameters if they are determined to be unused in `instance.def`. pub fn polymorphize(self, tcx: TyCtxt<'tcx>) -> Self { diff --git a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs index c0e1360640fd2..c472d4a5a4dc2 100644 --- a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs +++ b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs @@ -115,6 +115,8 @@ impl<'tcx> TyCtxt<'tcx> { /// Monomorphizes a type from the AST by first applying the /// in-scope substitutions and then normalizing any associated /// types. + /// Panics if normalization fails. In case normalization might fail + /// use `try_subst_and_normalize_erasing_regions` instead. pub fn subst_and_normalize_erasing_regions( self, param_substs: SubstsRef<'tcx>, @@ -134,6 +136,30 @@ impl<'tcx> TyCtxt<'tcx> { let substituted = value.subst(self, param_substs); self.normalize_erasing_regions(param_env, substituted) } + + /// Monomorphizes a type from the AST by first applying the + /// in-scope substitutions and then trying to normalize any associated + /// types. Contrary to `subst_and_normalize_erasing_regions` this does + /// not assume that normalization succeeds. + pub fn try_subst_and_normalize_erasing_regions( + self, + param_substs: SubstsRef<'tcx>, + param_env: ty::ParamEnv<'tcx>, + value: T, + ) -> Result> + where + T: TypeFoldable<'tcx>, + { + debug!( + "subst_and_normalize_erasing_regions(\ + param_substs={:?}, \ + value={:?}, \ + param_env={:?})", + param_substs, value, param_env, + ); + let substituted = value.subst(self, param_substs); + self.try_normalize_erasing_regions(param_env, substituted) + } } struct NormalizeAfterErasingRegionsFolder<'tcx> { From 3f831c64ccd210754d16d6ab9c287b02e3d3eabe Mon Sep 17 00:00:00 2001 From: b-naber Date: Sun, 5 Dec 2021 12:35:49 +0100 Subject: [PATCH 05/20] add test and bless existing ones --- .../ui/const-generics/issues/issue-72845.rs | 49 +++++++++++++++++++ .../const-generics/issues/issue-72845.stderr | 12 +++++ .../const-eval/const-eval-query-stack.stderr | 2 +- 3 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/const-generics/issues/issue-72845.rs create mode 100644 src/test/ui/const-generics/issues/issue-72845.stderr diff --git a/src/test/ui/const-generics/issues/issue-72845.rs b/src/test/ui/const-generics/issues/issue-72845.rs new file mode 100644 index 0000000000000..bea5dc8ba21e6 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-72845.rs @@ -0,0 +1,49 @@ +#![feature(generic_const_exprs)] +#![feature(specialization)] +#![allow(incomplete_features)] + +//-------------------------------------------------- + +trait Depth { + const C: usize; +} + +trait Type { + type AT: Depth; +} + +//-------------------------------------------------- + +enum Predicate {} + +trait Satisfied {} + +impl Satisfied for Predicate {} + +//-------------------------------------------------- + +trait Spec1 {} + +impl Spec1 for T where Predicate<{T::AT::C > 0}>: Satisfied {} + +trait Spec2 {} + +//impl Spec2 for T where Predicate<{T::AT::C > 1}>: Satisfied {} +impl Spec2 for T where Predicate: Satisfied {} + +//-------------------------------------------------- + +trait Foo { + fn Bar(); +} + +impl Foo for T { + default fn Bar() {} +} + +impl Foo for T { +//~^ ERROR conflicting implementations of trait + fn Bar() {} +} + +fn main() {} diff --git a/src/test/ui/const-generics/issues/issue-72845.stderr b/src/test/ui/const-generics/issues/issue-72845.stderr new file mode 100644 index 0000000000000..631c8605fb4d6 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-72845.stderr @@ -0,0 +1,12 @@ +error[E0119]: conflicting implementations of trait `Foo` + --> $DIR/issue-72845.rs:44:1 + | +LL | impl Foo for T { + | ------------------------ first implementation here +... +LL | impl Foo for T { + | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/src/test/ui/consts/const-eval/const-eval-query-stack.stderr b/src/test/ui/consts/const-eval/const-eval-query-stack.stderr index e6fecef9fb3b2..45a3d901c9871 100644 --- a/src/test/ui/consts/const-eval/const-eval-query-stack.stderr +++ b/src/test/ui/consts/const-eval/const-eval-query-stack.stderr @@ -20,7 +20,7 @@ error[E0080]: evaluation of constant value failed LL | let x: &'static i32 = &X; | ^ referenced constant has errors query stack during panic: -#0 [normalize_mir_const_after_erasing_regions] normalizing `main::promoted[1]` +#0 [try_normalize_mir_const_after_erasing_regions] normalizing `main::promoted[1]` #1 [optimized_mir] optimizing MIR for `main` #2 [collect_and_partition_mono_items] collect_and_partition_mono_items end of query stack From 2a95958248b243a14844cf2172edf2c3ad305670 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Sun, 5 Dec 2021 21:38:37 +0000 Subject: [PATCH 06/20] Evaluate inline const pat early and report error if too generic --- .../rustc_mir_build/src/thir/pattern/mod.rs | 83 ++++++++++++------- .../inline-const/const-match-pat-generic.rs | 25 ++++-- .../const-match-pat-generic.stderr | 20 ++++- 3 files changed, 88 insertions(+), 40 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index ce80214c875fc..55cf807172e02 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -533,43 +533,64 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { } } + /// Converts inline const patterns. + fn lower_inline_const( + &mut self, + anon_const: &'tcx hir::AnonConst, + id: hir::HirId, + span: Span, + ) -> PatKind<'tcx> { + let anon_const_def_id = self.tcx.hir().local_def_id(anon_const.hir_id); + let value = ty::Const::from_inline_const(self.tcx, anon_const_def_id); + + // Evaluate early like we do in `lower_path`. + let value = value.eval(self.tcx, self.param_env); + + match value.val { + ConstKind::Param(_) => { + self.errors.push(PatternError::ConstParamInPattern(span)); + return PatKind::Wild; + } + ConstKind::Unevaluated(_) => { + // If we land here it means the const can't be evaluated because it's `TooGeneric`. + self.tcx.sess.span_err(span, "constant pattern depends on a generic parameter"); + return PatKind::Wild; + } + _ => (), + } + + *self.const_to_pat(value, id, span, false).kind + } + /// Converts literals, paths and negation of literals to patterns. /// The special case for negation exists to allow things like `-128_i8` /// which would overflow if we tried to evaluate `128_i8` and then negate /// afterwards. fn lower_lit(&mut self, expr: &'tcx hir::Expr<'tcx>) -> PatKind<'tcx> { - if let hir::ExprKind::Path(ref qpath) = expr.kind { - *self.lower_path(qpath, expr.hir_id, expr.span).kind - } else { - let (lit, neg) = match expr.kind { - hir::ExprKind::ConstBlock(ref anon_const) => { - let anon_const_def_id = self.tcx.hir().local_def_id(anon_const.hir_id); - let value = ty::Const::from_inline_const(self.tcx, anon_const_def_id); - if matches!(value.val, ConstKind::Param(_)) { - let span = self.tcx.hir().span(anon_const.hir_id); - self.errors.push(PatternError::ConstParamInPattern(span)); - return PatKind::Wild; - } - return *self.const_to_pat(value, expr.hir_id, expr.span, false).kind; - } - hir::ExprKind::Lit(ref lit) => (lit, false), - hir::ExprKind::Unary(hir::UnOp::Neg, ref expr) => { - let lit = match expr.kind { - hir::ExprKind::Lit(ref lit) => lit, - _ => span_bug!(expr.span, "not a literal: {:?}", expr), - }; - (lit, true) - } - _ => span_bug!(expr.span, "not a literal: {:?}", expr), - }; - - let lit_input = - LitToConstInput { lit: &lit.node, ty: self.typeck_results.expr_ty(expr), neg }; - match self.tcx.at(expr.span).lit_to_const(lit_input) { - Ok(val) => *self.const_to_pat(val, expr.hir_id, lit.span, false).kind, - Err(LitToConstError::Reported) => PatKind::Wild, - Err(LitToConstError::TypeError) => bug!("lower_lit: had type error"), + let (lit, neg) = match expr.kind { + hir::ExprKind::Path(ref qpath) => { + return *self.lower_path(qpath, expr.hir_id, expr.span).kind; + } + hir::ExprKind::ConstBlock(ref anon_const) => { + return self.lower_inline_const(anon_const, expr.hir_id, expr.span); + } + hir::ExprKind::Lit(ref lit) => (lit, false), + hir::ExprKind::Unary(hir::UnOp::Neg, ref expr) => { + let lit = match expr.kind { + hir::ExprKind::Lit(ref lit) => lit, + _ => span_bug!(expr.span, "not a literal: {:?}", expr), + }; + (lit, true) } + _ => span_bug!(expr.span, "not a literal: {:?}", expr), + }; + + let lit_input = + LitToConstInput { lit: &lit.node, ty: self.typeck_results.expr_ty(expr), neg }; + match self.tcx.at(expr.span).lit_to_const(lit_input) { + Ok(val) => *self.const_to_pat(val, expr.hir_id, lit.span, false).kind, + Err(LitToConstError::Reported) => PatKind::Wild, + Err(LitToConstError::TypeError) => bug!("lower_lit: had type error"), } } } diff --git a/src/test/ui/inline-const/const-match-pat-generic.rs b/src/test/ui/inline-const/const-match-pat-generic.rs index 4486411698af9..be7e1d8d44984 100644 --- a/src/test/ui/inline-const/const-match-pat-generic.rs +++ b/src/test/ui/inline-const/const-match-pat-generic.rs @@ -1,16 +1,31 @@ #![allow(incomplete_features)] #![feature(inline_const_pat)] +#![feature(generic_const_exprs)] // rust-lang/rust#82518: ICE with inline-const in match referencing const-generic parameter fn foo() { - match 0 { - const { V } => {}, - //~^ ERROR const parameters cannot be referenced in patterns [E0158] - _ => {}, - } + match 0 { + const { V } => {}, + //~^ ERROR const parameters cannot be referenced in patterns [E0158] + _ => {}, + } +} + +const fn f(x: usize) -> usize { + x + 1 +} + +fn bar() where [(); f(V)]: { + match 0 { + const { f(V) } => {}, + //~^ ERROR constant pattern depends on a generic parameter + //~| ERROR constant pattern depends on a generic parameter + _ => {}, + } } fn main() { foo::<1>(); + bar::<1>(); } diff --git a/src/test/ui/inline-const/const-match-pat-generic.stderr b/src/test/ui/inline-const/const-match-pat-generic.stderr index a3ed41a3f6af8..5fe5a7a6dad41 100644 --- a/src/test/ui/inline-const/const-match-pat-generic.stderr +++ b/src/test/ui/inline-const/const-match-pat-generic.stderr @@ -1,9 +1,21 @@ error[E0158]: const parameters cannot be referenced in patterns - --> $DIR/const-match-pat-generic.rs:8:11 + --> $DIR/const-match-pat-generic.rs:9:9 | -LL | const { V } => {}, - | ^^^^^ +LL | const { V } => {}, + | ^^^^^^^^^^^ -error: aborting due to previous error +error: constant pattern depends on a generic parameter + --> $DIR/const-match-pat-generic.rs:21:9 + | +LL | const { f(V) } => {}, + | ^^^^^^^^^^^^^^ + +error: constant pattern depends on a generic parameter + --> $DIR/const-match-pat-generic.rs:21:9 + | +LL | const { f(V) } => {}, + | ^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0158`. From 97952f46f5bb201a5787ea3570310053b99c18e7 Mon Sep 17 00:00:00 2001 From: Nixon Enraght-Moony Date: Mon, 6 Dec 2021 23:28:32 +0000 Subject: [PATCH 07/20] Link to rustdoc_json_types docs instead of rustdoc-json RFC --- src/doc/rustdoc/src/unstable-features.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index 021040215437e..56ca7c0392800 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -396,7 +396,7 @@ Note that the third item is the crate root, which in this case is undocumented. ### `-w`/`--output-format`: output format `--output-format json` emits documentation in the experimental -[JSON format](https://github.com/rust-lang/rfcs/pull/2963). `--output-format html` has no effect, +[JSON format](https://doc.rust-lang.org/nightly/nightly-rustc/rustdoc_json_types/). `--output-format html` has no effect, and is also accepted on stable toolchains. It can also be used with `--show-coverage`. Take a look at its From 78e88f46d60c5487946fc7632a7561bdff6b9fcc Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Mon, 8 Nov 2021 19:15:54 +0000 Subject: [PATCH 08/20] Only shown relevant type params in E0283 label When we point at a binding to suggest giving it a type, erase all the type for ADTs that have been resolved, leaving only the ones that could not be inferred. For small shallow types this is not a problem, but for big nested types with lots of params, this can otherwise cause a lot of unnecessary visual output. --- .../infer/error_reporting/need_type_info.rs | 100 +++++++++++++++++- .../defaults/doesnt_infer.stderr | 2 +- .../inference/erase-type-params-in-label.rs | 13 +++ .../erase-type-params-in-label.stderr | 22 ++++ src/test/ui/inference/issue-83606.stderr | 2 +- 5 files changed, 136 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/inference/erase-type-params-in-label.rs create mode 100644 src/test/ui/inference/erase-type-params-in-label.stderr diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index 32c02033dc9b9..6b9952ba5d684 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -11,7 +11,7 @@ use rustc_middle::hir::map::Map; use rustc_middle::infer::unify_key::ConstVariableOriginKind; use rustc_middle::ty::print::Print; use rustc_middle::ty::subst::{GenericArg, GenericArgKind}; -use rustc_middle::ty::{self, DefIdTree, InferConst, Ty, TyCtxt}; +use rustc_middle::ty::{self, DefIdTree, InferConst, Ty, TyCtxt, TypeFoldable, TypeFolder}; use rustc_span::symbol::kw; use rustc_span::Span; use std::borrow::Cow; @@ -629,6 +629,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { format!("the explicit type `{}`, with the type parameters specified", ty) } Some(ty) if is_named_and_not_impl_trait(ty) && ty.to_string() != arg_data.name => { + let ty = ResolvedTypeParamEraser::new(self.tcx).fold_ty(ty); + let ty = ErrTypeParamEraser(self.tcx).fold_ty(ty); let ty = ty_to_string(ty); format!( "the explicit type `{}`, where the type parameter `{}` is specified", @@ -908,3 +910,99 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { err } } + +/// Turn resolved type params into `[type error]` to signal we don't want to display them. +struct ResolvedTypeParamEraser<'tcx> { + tcx: TyCtxt<'tcx>, + level: usize, +} + +impl<'tcx> ResolvedTypeParamEraser<'tcx> { + fn new(tcx: TyCtxt<'tcx>) -> Self { + ResolvedTypeParamEraser { tcx, level: 0 } + } +} +impl<'tcx> TypeFolder<'tcx> for ResolvedTypeParamEraser<'tcx> { + fn tcx<'a>(&'a self) -> TyCtxt<'tcx> { + self.tcx + } + fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { + self.level += 1; + let t = match t.kind() { + // We'll hide this type only if all its type params are hidden as well. + ty::Adt(def, substs) => { + let generics = self.tcx().generics_of(def.did); + // Account for params with default values, like `Vec`, where we + // want to show `Vec`, not `Vec`. If we replaced that + // subst, then we'd get the incorrect output, so we passthrough. + let substs: Vec<_> = substs + .iter() + .zip(generics.params.iter()) + .map(|(subst, param)| match ¶m.kind { + ty::GenericParamDefKind::Type { has_default: true, .. } => subst, + _ => subst.super_fold_with(self), + }) + .collect(); + if self.level == 1 + || substs.iter().any(|subst| match subst.unpack() { + ty::subst::GenericArgKind::Type(t) => match t.kind() { + ty::Error(_) => false, + _ => true, + }, + // Account for `const` params here, otherwise `doesnt_infer.rs` + // shows `_` instead of `Foo<{ _: u32 }>` + ty::subst::GenericArgKind::Const(_) => true, + _ => false, + }) + { + let substs = self.tcx().intern_substs(&substs[..]); + self.tcx().mk_ty(ty::Adt(def, substs)) + } else { + self.tcx().ty_error() + } + } + ty::Ref(_, ty, _) => { + let ty = self.fold_ty(ty); + match ty.kind() { + // Avoid `&_`, these can be safely presented as `_`. + ty::Error(_) => self.tcx().ty_error(), + _ => t.super_fold_with(self), + } + } + // We could account for `()` if we wanted to replace it, but it's assured to be short. + ty::Tuple(_) + | ty::Slice(_) + | ty::RawPtr(_) + | ty::FnDef(..) + | ty::FnPtr(_) + | ty::Opaque(..) + | ty::Projection(_) + | ty::Never + | ty::Array(..) => t.super_fold_with(self), + // We don't want to hide type params that haven't been resolved yet. + // This would be the type that will be written out with the type param + // name in the output. + ty::Infer(_) => t, + // We don't want to hide the outermost type, only its type params. + _ if self.level == 1 => t.super_fold_with(self), + // Hide this type + _ => self.tcx().ty_error(), + }; + self.level -= 1; + t + } +} + +/// Replace `[type error]` with `ty::Infer(ty::Var)` to display `_`. +struct ErrTypeParamEraser<'tcx>(TyCtxt<'tcx>); +impl<'tcx> TypeFolder<'tcx> for ErrTypeParamEraser<'tcx> { + fn tcx<'a>(&'a self) -> TyCtxt<'tcx> { + self.0 + } + fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { + match t.kind() { + ty::Error(_) => self.tcx().mk_ty_var(ty::TyVid::from_u32(0)), + _ => t.super_fold_with(self), + } + } +} diff --git a/src/test/ui/const-generics/defaults/doesnt_infer.stderr b/src/test/ui/const-generics/defaults/doesnt_infer.stderr index b57975e26f290..183be1b1517a7 100644 --- a/src/test/ui/const-generics/defaults/doesnt_infer.stderr +++ b/src/test/ui/const-generics/defaults/doesnt_infer.stderr @@ -4,7 +4,7 @@ error[E0282]: type annotations needed for `Foo<{_: u32}>` LL | let foo = Foo::foo(); | --- ^^^^^^^^ cannot infer the value of const parameter `N` | | - | consider giving `foo` the explicit type `Foo<{_: u32}>`, where the type parameter `N` is specified + | consider giving `foo` the explicit type `Foo<{_: _}>`, where the type parameter `N` is specified error: aborting due to previous error diff --git a/src/test/ui/inference/erase-type-params-in-label.rs b/src/test/ui/inference/erase-type-params-in-label.rs new file mode 100644 index 0000000000000..4a163d0b81094 --- /dev/null +++ b/src/test/ui/inference/erase-type-params-in-label.rs @@ -0,0 +1,13 @@ +fn main() { + let foo = new(1, ""); //~ ERROR E0283 +} + +struct Bar { + t: T, + k: K, + n: N, +} + +fn new(t: T, k: K) -> Bar { + Bar { t, k, n: Default::default() } +} diff --git a/src/test/ui/inference/erase-type-params-in-label.stderr b/src/test/ui/inference/erase-type-params-in-label.stderr new file mode 100644 index 0000000000000..b665fade9d88f --- /dev/null +++ b/src/test/ui/inference/erase-type-params-in-label.stderr @@ -0,0 +1,22 @@ +error[E0283]: type annotations needed for `Bar` + --> $DIR/erase-type-params-in-label.rs:2:15 + | +LL | let foo = new(1, ""); + | --- ^^^ cannot infer type for type parameter `Z` declared on the function `new` + | | + | consider giving `foo` the explicit type `Bar<_, _, Z>`, where the type parameter `Z` is specified + | + = note: cannot satisfy `_: Default` +note: required by a bound in `new` + --> $DIR/erase-type-params-in-label.rs:11:17 + | +LL | fn new(t: T, k: K) -> Bar { + | ^^^^^^^ required by this bound in `new` +help: consider specifying the type arguments in the function call + | +LL | let foo = new::(1, ""); + | +++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0283`. diff --git a/src/test/ui/inference/issue-83606.stderr b/src/test/ui/inference/issue-83606.stderr index 65f3336b9358a..c66606b9c8304 100644 --- a/src/test/ui/inference/issue-83606.stderr +++ b/src/test/ui/inference/issue-83606.stderr @@ -4,7 +4,7 @@ error[E0282]: type annotations needed for `[usize; _]` LL | let _ = foo("foo"); //<- Do not suggest `foo::("foo");`! | - ^^^ cannot infer the value of const parameter `N` declared on the function `foo` | | - | consider giving this pattern the explicit type `[usize; _]`, where the type parameter `N` is specified + | consider giving this pattern the explicit type `[_; _]`, where the type parameter `N` is specified error: aborting due to previous error From 3fd15c8404626c6622555e66299c9f3442bf2322 Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Mon, 8 Nov 2021 20:32:17 +0000 Subject: [PATCH 09/20] Refer to uninferred `const` params by their name, instead of `{ _: _ }` When the value of a const param isn't inferred, replace it with the param name from the definition. --- .../infer/error_reporting/need_type_info.rs | 31 +++++++++++++++---- .../defaults/doesnt_infer.stderr | 2 +- src/test/ui/inference/issue-83606.stderr | 2 +- 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index 6b9952ba5d684..56f0b5c192786 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -1,6 +1,5 @@ use crate::infer::type_variable::TypeVariableOriginKind; -use crate::infer::InferCtxt; -use crate::rustc_middle::ty::TypeFoldable; +use crate::infer::{InferCtxt, Symbol}; use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Namespace}; @@ -938,8 +937,17 @@ impl<'tcx> TypeFolder<'tcx> for ResolvedTypeParamEraser<'tcx> { let substs: Vec<_> = substs .iter() .zip(generics.params.iter()) - .map(|(subst, param)| match ¶m.kind { - ty::GenericParamDefKind::Type { has_default: true, .. } => subst, + .map(|(subst, param)| match &(subst.unpack(), ¶m.kind) { + (_, ty::GenericParamDefKind::Type { has_default: true, .. }) => subst, + (crate::infer::GenericArgKind::Const(c), _) => { + match c.val { + ty::ConstKind::Infer(..) => { + // Replace not yet inferred const params with their def name. + self.tcx().mk_const_param(param.index, param.name, c.ty).into() + } + _ => subst, + } + } _ => subst.super_fold_with(self), }) .collect(); @@ -977,8 +985,19 @@ impl<'tcx> TypeFolder<'tcx> for ResolvedTypeParamEraser<'tcx> { | ty::FnPtr(_) | ty::Opaque(..) | ty::Projection(_) - | ty::Never - | ty::Array(..) => t.super_fold_with(self), + | ty::Never => t.super_fold_with(self), + ty::Array(ty, c) => { + self.tcx().mk_ty(ty::Array( + self.fold_ty(ty), + match c.val { + ty::ConstKind::Infer(..) => { + // Replace not yet inferred const params with their def name. + self.tcx().mk_const_param(0, Symbol::intern("N"), c.ty).into() + } + _ => c, + }, + )) + } // We don't want to hide type params that haven't been resolved yet. // This would be the type that will be written out with the type param // name in the output. diff --git a/src/test/ui/const-generics/defaults/doesnt_infer.stderr b/src/test/ui/const-generics/defaults/doesnt_infer.stderr index 183be1b1517a7..10cd491b480c1 100644 --- a/src/test/ui/const-generics/defaults/doesnt_infer.stderr +++ b/src/test/ui/const-generics/defaults/doesnt_infer.stderr @@ -4,7 +4,7 @@ error[E0282]: type annotations needed for `Foo<{_: u32}>` LL | let foo = Foo::foo(); | --- ^^^^^^^^ cannot infer the value of const parameter `N` | | - | consider giving `foo` the explicit type `Foo<{_: _}>`, where the type parameter `N` is specified + | consider giving `foo` the explicit type `Foo`, where the type parameter `N` is specified error: aborting due to previous error diff --git a/src/test/ui/inference/issue-83606.stderr b/src/test/ui/inference/issue-83606.stderr index c66606b9c8304..0746b2491fbd6 100644 --- a/src/test/ui/inference/issue-83606.stderr +++ b/src/test/ui/inference/issue-83606.stderr @@ -4,7 +4,7 @@ error[E0282]: type annotations needed for `[usize; _]` LL | let _ = foo("foo"); //<- Do not suggest `foo::("foo");`! | - ^^^ cannot infer the value of const parameter `N` declared on the function `foo` | | - | consider giving this pattern the explicit type `[_; _]`, where the type parameter `N` is specified + | consider giving this pattern the explicit type `[_; N]`, where the type parameter `N` is specified error: aborting due to previous error From 6a691b1d92c0c34ee8b43a6d04df30c908c4d6a3 Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Mon, 8 Nov 2021 21:10:00 +0000 Subject: [PATCH 10/20] Refer to const params as "const params" and not "type params" --- .../infer/error_reporting/need_type_info.rs | 82 +++++++++++-------- .../defaults/doesnt_infer.stderr | 2 +- src/test/ui/inference/issue-83606.stderr | 2 +- 3 files changed, 48 insertions(+), 38 deletions(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index 56f0b5c192786..739987e850a01 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -10,7 +10,7 @@ use rustc_middle::hir::map::Map; use rustc_middle::infer::unify_key::ConstVariableOriginKind; use rustc_middle::ty::print::Print; use rustc_middle::ty::subst::{GenericArg, GenericArgKind}; -use rustc_middle::ty::{self, DefIdTree, InferConst, Ty, TyCtxt, TypeFoldable, TypeFolder}; +use rustc_middle::ty::{self, Const, DefIdTree, InferConst, Ty, TyCtxt, TypeFoldable, TypeFolder}; use rustc_span::symbol::kw; use rustc_span::Span; use std::borrow::Cow; @@ -305,6 +305,15 @@ pub enum UnderspecifiedArgKind { Const { is_parameter: bool }, } +impl UnderspecifiedArgKind { + fn descr(&self) -> &'static str { + match self { + Self::Type { .. } => "type", + Self::Const { .. } => "const", + } + } +} + impl InferenceDiagnosticsData { /// Generate a label for a generic argument which can't be inferred. When not /// much is known about the argument, `use_diag` may be used to describe the @@ -587,6 +596,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } + let param_type = arg_data.kind.descr(); let suffix = match local_visitor.found_node_ty { Some(ty) if ty.is_closure() => { let substs = @@ -625,15 +635,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } Some(ty) if is_named_and_not_impl_trait(ty) && arg_data.name == "_" => { let ty = ty_to_string(ty); - format!("the explicit type `{}`, with the type parameters specified", ty) + format!("the explicit type `{}`, with the {} parameters specified", ty, param_type) } Some(ty) if is_named_and_not_impl_trait(ty) && ty.to_string() != arg_data.name => { let ty = ResolvedTypeParamEraser::new(self.tcx).fold_ty(ty); let ty = ErrTypeParamEraser(self.tcx).fold_ty(ty); let ty = ty_to_string(ty); format!( - "the explicit type `{}`, where the type parameter `{}` is specified", - ty, arg_data.name, + "the explicit type `{}`, where the {} parameter `{}` is specified", + ty, param_type, arg_data.name, ) } _ => "a type".to_string(), @@ -910,7 +920,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } -/// Turn resolved type params into `[type error]` to signal we don't want to display them. +/// Turn *resolved* type params into `[type error]` to signal we don't want to display them. After +/// performing that replacement, we'll turn all remaining infer type params to use their name from +/// their definition, and replace all the `[type error]`s back to being infer so they display in +/// the output as `_`. If we didn't go through `[type error]`, we would either show all type params +/// by their name *or* `_`, neither of which is desireable: we want to show all types that we could +/// infer as `_` to reduce verbosity and avoid telling the user about unnecessary type annotations. struct ResolvedTypeParamEraser<'tcx> { tcx: TyCtxt<'tcx>, level: usize, @@ -920,7 +935,18 @@ impl<'tcx> ResolvedTypeParamEraser<'tcx> { fn new(tcx: TyCtxt<'tcx>) -> Self { ResolvedTypeParamEraser { tcx, level: 0 } } + + /// Replace not yet inferred const params with their def name. + fn replace_infers(&self, c: &'tcx Const<'tcx>, index: u32, name: Symbol) -> &'tcx Const<'tcx> { + match c.val { + ty::ConstKind::Infer(..) => { + self.tcx().mk_const_param(index, name, c.ty) + } + _ => c, + } + } } + impl<'tcx> TypeFolder<'tcx> for ResolvedTypeParamEraser<'tcx> { fn tcx<'a>(&'a self) -> TyCtxt<'tcx> { self.tcx @@ -940,29 +966,22 @@ impl<'tcx> TypeFolder<'tcx> for ResolvedTypeParamEraser<'tcx> { .map(|(subst, param)| match &(subst.unpack(), ¶m.kind) { (_, ty::GenericParamDefKind::Type { has_default: true, .. }) => subst, (crate::infer::GenericArgKind::Const(c), _) => { - match c.val { - ty::ConstKind::Infer(..) => { - // Replace not yet inferred const params with their def name. - self.tcx().mk_const_param(param.index, param.name, c.ty).into() - } - _ => subst, - } + self.replace_infers(c, param.index, param.name).into() } _ => subst.super_fold_with(self), }) .collect(); - if self.level == 1 - || substs.iter().any(|subst| match subst.unpack() { - ty::subst::GenericArgKind::Type(t) => match t.kind() { - ty::Error(_) => false, - _ => true, - }, - // Account for `const` params here, otherwise `doesnt_infer.rs` - // shows `_` instead of `Foo<{ _: u32 }>` - ty::subst::GenericArgKind::Const(_) => true, - _ => false, - }) - { + let should_keep = |subst: &GenericArg<'_>| match subst.unpack() { + ty::subst::GenericArgKind::Type(t) => match t.kind() { + ty::Error(_) => false, + _ => true, + }, + // Account for `const` params here, otherwise `doesnt_infer.rs` + // shows `_` instead of `Foo<{ _: u32 }>` + ty::subst::GenericArgKind::Const(_) => true, + _ => false, + }; + if self.level == 1 || substs.iter().any(should_keep) { let substs = self.tcx().intern_substs(&substs[..]); self.tcx().mk_ty(ty::Adt(def, substs)) } else { @@ -986,18 +1005,9 @@ impl<'tcx> TypeFolder<'tcx> for ResolvedTypeParamEraser<'tcx> { | ty::Opaque(..) | ty::Projection(_) | ty::Never => t.super_fold_with(self), - ty::Array(ty, c) => { - self.tcx().mk_ty(ty::Array( - self.fold_ty(ty), - match c.val { - ty::ConstKind::Infer(..) => { - // Replace not yet inferred const params with their def name. - self.tcx().mk_const_param(0, Symbol::intern("N"), c.ty).into() - } - _ => c, - }, - )) - } + ty::Array(ty, c) => self + .tcx() + .mk_ty(ty::Array(self.fold_ty(ty), self.replace_infers(c, 0, Symbol::intern("N")))), // We don't want to hide type params that haven't been resolved yet. // This would be the type that will be written out with the type param // name in the output. diff --git a/src/test/ui/const-generics/defaults/doesnt_infer.stderr b/src/test/ui/const-generics/defaults/doesnt_infer.stderr index 10cd491b480c1..d6c64d58be5f3 100644 --- a/src/test/ui/const-generics/defaults/doesnt_infer.stderr +++ b/src/test/ui/const-generics/defaults/doesnt_infer.stderr @@ -4,7 +4,7 @@ error[E0282]: type annotations needed for `Foo<{_: u32}>` LL | let foo = Foo::foo(); | --- ^^^^^^^^ cannot infer the value of const parameter `N` | | - | consider giving `foo` the explicit type `Foo`, where the type parameter `N` is specified + | consider giving `foo` the explicit type `Foo`, where the const parameter `N` is specified error: aborting due to previous error diff --git a/src/test/ui/inference/issue-83606.stderr b/src/test/ui/inference/issue-83606.stderr index 0746b2491fbd6..9ca8f35fd545a 100644 --- a/src/test/ui/inference/issue-83606.stderr +++ b/src/test/ui/inference/issue-83606.stderr @@ -4,7 +4,7 @@ error[E0282]: type annotations needed for `[usize; _]` LL | let _ = foo("foo"); //<- Do not suggest `foo::("foo");`! | - ^^^ cannot infer the value of const parameter `N` declared on the function `foo` | | - | consider giving this pattern the explicit type `[_; N]`, where the type parameter `N` is specified + | consider giving this pattern the explicit type `[_; N]`, where the const parameter `N` is specified error: aborting due to previous error From 7271d1f803ba4a2f850d19c570d04993b61881a9 Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Fri, 19 Nov 2021 06:10:43 +0000 Subject: [PATCH 11/20] Add test with multiple type params failing inference --- .../infer/error_reporting/need_type_info.rs | 4 +- .../inference/erase-type-params-in-label.rs | 18 ++++++++- .../erase-type-params-in-label.stderr | 39 ++++++++++++++----- 3 files changed, 46 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index 739987e850a01..9cf6cde259150 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -939,9 +939,7 @@ impl<'tcx> ResolvedTypeParamEraser<'tcx> { /// Replace not yet inferred const params with their def name. fn replace_infers(&self, c: &'tcx Const<'tcx>, index: u32, name: Symbol) -> &'tcx Const<'tcx> { match c.val { - ty::ConstKind::Infer(..) => { - self.tcx().mk_const_param(index, name, c.ty) - } + ty::ConstKind::Infer(..) => self.tcx().mk_const_param(index, name, c.ty), _ => c, } } diff --git a/src/test/ui/inference/erase-type-params-in-label.rs b/src/test/ui/inference/erase-type-params-in-label.rs index 4a163d0b81094..1fea2da92da94 100644 --- a/src/test/ui/inference/erase-type-params-in-label.rs +++ b/src/test/ui/inference/erase-type-params-in-label.rs @@ -1,5 +1,8 @@ fn main() { - let foo = new(1, ""); //~ ERROR E0283 + let foo = foo(1, ""); //~ ERROR E0283 +} +fn baz() { + let bar = bar(1, ""); //~ ERROR E0283 } struct Bar { @@ -8,6 +11,17 @@ struct Bar { n: N, } -fn new(t: T, k: K) -> Bar { +fn bar(t: T, k: K) -> Bar { Bar { t, k, n: Default::default() } } + +struct Foo { + t: T, + k: K, + n: N, + m: M, +} + +fn foo(t: T, k: K) -> Foo { + Foo { t, k, n: Default::default(), m: Default::default() } +} diff --git a/src/test/ui/inference/erase-type-params-in-label.stderr b/src/test/ui/inference/erase-type-params-in-label.stderr index b665fade9d88f..d0b06cde9d63a 100644 --- a/src/test/ui/inference/erase-type-params-in-label.stderr +++ b/src/test/ui/inference/erase-type-params-in-label.stderr @@ -1,22 +1,41 @@ -error[E0283]: type annotations needed for `Bar` +error[E0283]: type annotations needed for `Foo` --> $DIR/erase-type-params-in-label.rs:2:15 | -LL | let foo = new(1, ""); - | --- ^^^ cannot infer type for type parameter `Z` declared on the function `new` +LL | let foo = foo(1, ""); + | --- ^^^ cannot infer type for type parameter `W` declared on the function `foo` + | | + | consider giving `foo` the explicit type `Foo<_, _, W, Z>`, where the type parameter `W` is specified + | + = note: cannot satisfy `_: Default` +note: required by a bound in `foo` + --> $DIR/erase-type-params-in-label.rs:25:17 + | +LL | fn foo(t: T, k: K) -> Foo { + | ^^^^^^^ required by this bound in `foo` +help: consider specifying the type arguments in the function call + | +LL | let foo = foo::(1, ""); + | ++++++++++++++ + +error[E0283]: type annotations needed for `Bar` + --> $DIR/erase-type-params-in-label.rs:5:15 + | +LL | let bar = bar(1, ""); + | --- ^^^ cannot infer type for type parameter `Z` declared on the function `bar` | | - | consider giving `foo` the explicit type `Bar<_, _, Z>`, where the type parameter `Z` is specified + | consider giving `bar` the explicit type `Bar<_, _, Z>`, where the type parameter `Z` is specified | = note: cannot satisfy `_: Default` -note: required by a bound in `new` - --> $DIR/erase-type-params-in-label.rs:11:17 +note: required by a bound in `bar` + --> $DIR/erase-type-params-in-label.rs:14:17 | -LL | fn new(t: T, k: K) -> Bar { - | ^^^^^^^ required by this bound in `new` +LL | fn bar(t: T, k: K) -> Bar { + | ^^^^^^^ required by this bound in `bar` help: consider specifying the type arguments in the function call | -LL | let foo = new::(1, ""); +LL | let bar = bar::(1, ""); | +++++++++++ -error: aborting due to previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0283`. From 4aceaedb5e1629cd4f6f38638fdcf19919c05619 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 6 Dec 2021 20:33:00 -0800 Subject: [PATCH 12/20] Update cargo --- Cargo.lock | 6 +++--- src/tools/cargo | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2233162be3b6b..16275f311ad36 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -558,11 +558,11 @@ dependencies = [ [[package]] name = "clap" -version = "2.33.3" +version = "2.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" dependencies = [ - "ansi_term 0.11.0", + "ansi_term 0.12.1", "atty", "bitflags", "strsim", diff --git a/src/tools/cargo b/src/tools/cargo index 294967c53f0c7..40dc281755137 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 294967c53f0c70d598fc54ca189313c86c576ea7 +Subproject commit 40dc281755137ee804bc9b3b08e782773b726e44 From 1b27b69e5a5464484e63f7eb324376c901fd3692 Mon Sep 17 00:00:00 2001 From: klensy Date: Tue, 7 Dec 2021 12:54:35 +0300 Subject: [PATCH 13/20] don't allocate strings when str is enought for using as key --- compiler/rustc_serialize/src/json.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_serialize/src/json.rs b/compiler/rustc_serialize/src/json.rs index df78e1bcbf63c..cb9df3c33898f 100644 --- a/compiler/rustc_serialize/src/json.rs +++ b/compiler/rustc_serialize/src/json.rs @@ -2320,12 +2320,12 @@ impl crate::Decoder for Decoder { let name = match self.pop() { Json::String(s) => s, Json::Object(mut o) => { - let n = match o.remove(&"variant".to_owned()) { + let n = match o.remove("variant") { Some(Json::String(s)) => s, Some(val) => return Err(ExpectedError("String".to_owned(), val.to_string())), None => return Err(MissingFieldError("variant".to_owned())), }; - match o.remove(&"fields".to_string()) { + match o.remove("fields") { Some(Json::Array(l)) => { self.stack.extend(l.into_iter().rev()); } @@ -2365,7 +2365,7 @@ impl crate::Decoder for Decoder { { let mut obj = expect!(self.pop(), Object)?; - let value = match obj.remove(&name.to_string()) { + let value = match obj.remove(name) { None => { // Add a Null and try to parse it as an Option<_> // to get None as a default value. From 4dd3f4e9ea820f0053abe624d2bdb3a8e4b10d5f Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 7 Dec 2021 15:11:00 +0100 Subject: [PATCH 14/20] Add missing whitespace before disabled HTML attribute --- src/librustdoc/html/templates/page.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustdoc/html/templates/page.html b/src/librustdoc/html/templates/page.html index 3c6f083419aef..5c957e4a379a4 100644 --- a/src/librustdoc/html/templates/page.html +++ b/src/librustdoc/html/templates/page.html @@ -20,7 +20,7 @@ id="mainThemeStyle"> {#- -#} {%- for theme in themes -%} Date: Sun, 5 Dec 2021 13:33:39 -0800 Subject: [PATCH 15/20] Remove unneeded access to pretty printer's `s` field in favor of deref --- compiler/rustc_ast_pretty/src/pprust/state.rs | 330 ++++++++-------- compiler/rustc_hir_pretty/src/lib.rs | 354 +++++++++--------- 2 files changed, 342 insertions(+), 342 deletions(-) diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 921ac785e815e..74f2a2b2e09d6 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -878,29 +878,29 @@ impl<'a> PrintState<'a> for State<'a> { } fn print_ident(&mut self, ident: Ident) { - self.s.word(IdentPrinter::for_ast_ident(ident, ident.is_raw_guess()).to_string()); + self.word(IdentPrinter::for_ast_ident(ident, ident.is_raw_guess()).to_string()); self.ann.post(self, AnnNode::Ident(&ident)) } fn print_generic_args(&mut self, args: &ast::GenericArgs, colons_before_params: bool) { if colons_before_params { - self.s.word("::") + self.word("::") } match *args { ast::GenericArgs::AngleBracketed(ref data) => { - self.s.word("<"); + self.word("<"); self.commasep(Inconsistent, &data.args, |s, arg| match arg { ast::AngleBracketedArg::Arg(a) => s.print_generic_arg(a), ast::AngleBracketedArg::Constraint(c) => s.print_assoc_constraint(c), }); - self.s.word(">") + self.word(">") } ast::GenericArgs::Parenthesized(ref data) => { - self.s.word("("); + self.word("("); self.commasep(Inconsistent, &data.inputs, |s, ty| s.print_type(ty)); - self.s.word(")"); + self.word(")"); self.print_fn_ret_ty(&data.output); } } @@ -925,7 +925,7 @@ impl<'a> State<'a> { op(self, elt); i += 1; if i < len { - self.s.word(","); + self.word(","); self.maybe_print_trailing_comment(get_span(elt), Some(get_span(&elts[i]).hi())); self.space_if_not_bol(); } @@ -954,7 +954,7 @@ impl<'a> State<'a> { pub fn print_assoc_constraint(&mut self, constraint: &ast::AssocTyConstraint) { self.print_ident(constraint.ident); constraint.gen_args.as_ref().map(|args| self.print_generic_args(args, false)); - self.s.space(); + self.space(); match &constraint.kind { ast::AssocTyConstraintKind::Equality { ty } => { self.word_space("="); @@ -979,27 +979,27 @@ impl<'a> State<'a> { self.ibox(0); match ty.kind { ast::TyKind::Slice(ref ty) => { - self.s.word("["); + self.word("["); self.print_type(ty); - self.s.word("]"); + self.word("]"); } ast::TyKind::Ptr(ref mt) => { - self.s.word("*"); + self.word("*"); self.print_mt(mt, true); } ast::TyKind::Rptr(ref lifetime, ref mt) => { - self.s.word("&"); + self.word("&"); self.print_opt_lifetime(lifetime); self.print_mt(mt, false); } ast::TyKind::Never => { - self.s.word("!"); + self.word("!"); } ast::TyKind::Tup(ref elts) => { self.popen(); self.commasep(Inconsistent, &elts[..], |s, ty| s.print_type(ty)); if elts.len() == 1 { - self.s.word(","); + self.word(","); } self.pclose(); } @@ -1023,33 +1023,33 @@ impl<'a> State<'a> { self.print_type_bounds("impl", &bounds[..]); } ast::TyKind::Array(ref ty, ref length) => { - self.s.word("["); + self.word("["); self.print_type(ty); - self.s.word("; "); + self.word("; "); self.print_expr(&length.value); - self.s.word("]"); + self.word("]"); } ast::TyKind::Typeof(ref e) => { - self.s.word("typeof("); + self.word("typeof("); self.print_expr(&e.value); - self.s.word(")"); + self.word(")"); } ast::TyKind::Infer => { - self.s.word("_"); + self.word("_"); } ast::TyKind::Err => { self.popen(); - self.s.word("/*ERROR*/"); + self.word("/*ERROR*/"); self.pclose(); } ast::TyKind::ImplicitSelf => { - self.s.word("Self"); + self.word("Self"); } ast::TyKind::MacCall(ref m) => { self.print_mac(m); } ast::TyKind::CVarArgs => { - self.s.word("..."); + self.word("..."); } } self.end(); @@ -1087,7 +1087,7 @@ impl<'a> State<'a> { ast::ForeignItemKind::MacCall(m) => { self.print_mac(m); if m.args.need_semicolon() { - self.s.word(";"); + self.word(";"); } } } @@ -1115,13 +1115,13 @@ impl<'a> State<'a> { self.print_ident(ident); self.word_space(":"); self.print_type(ty); - self.s.space(); + self.space(); self.end(); // end the head-ibox if let Some(body) = body { self.word_space("="); self.print_expr(body); } - self.s.word(";"); + self.word(";"); self.end(); // end the outer cbox } @@ -1143,11 +1143,11 @@ impl<'a> State<'a> { self.print_type_bounds(":", bounds); self.print_where_clause(&generics.where_clause); if let Some(ty) = ty { - self.s.space(); + self.space(); self.word_space("="); self.print_type(ty); } - self.s.word(";"); + self.word(";"); self.end(); // end inner head-block self.end(); // end outer head-block } @@ -1163,19 +1163,19 @@ impl<'a> State<'a> { self.head(visibility_qualified(&item.vis, "extern crate")); if let Some(orig_name) = orig_name { self.print_name(orig_name); - self.s.space(); - self.s.word("as"); - self.s.space(); + self.space(); + self.word("as"); + self.space(); } self.print_ident(item.ident); - self.s.word(";"); + self.word(";"); self.end(); // end inner head-block self.end(); // end outer head-block } ast::ItemKind::Use(ref tree) => { self.head(visibility_qualified(&item.vis, "use")); self.print_use_tree(tree); - self.s.word(";"); + self.word(";"); self.end(); // end inner head-block self.end(); // end outer head-block } @@ -1218,7 +1218,7 @@ impl<'a> State<'a> { self.bclose(item.span, empty); } ModKind::Unloaded => { - self.s.word(";"); + self.word(";"); self.end(); // end inner head-block self.end(); // end outer head-block } @@ -1289,23 +1289,23 @@ impl<'a> State<'a> { if !generics.params.is_empty() { self.print_generic_params(&generics.params); - self.s.space(); + self.space(); } if let ast::ImplPolarity::Negative(_) = polarity { - self.s.word("!"); + self.word("!"); } if let Some(ref t) = *of_trait { self.print_trait_ref(t); - self.s.space(); + self.space(); self.word_space("for"); } self.print_type(self_ty); self.print_where_clause(&generics.where_clause); - self.s.space(); + self.space(); self.bopen(); self.print_inner_attributes(&item.attrs); for impl_item in items { @@ -1332,7 +1332,7 @@ impl<'a> State<'a> { let mut real_bounds = Vec::with_capacity(bounds.len()); for b in bounds.iter() { if let GenericBound::Trait(ref ptr, ast::TraitBoundModifier::Maybe) = *b { - self.s.space(); + self.space(); self.word_space("for ?"); self.print_trait_ref(&ptr.trait_ref); } else { @@ -1341,7 +1341,7 @@ impl<'a> State<'a> { } self.print_type_bounds(":", &real_bounds[..]); self.print_where_clause(&generics.where_clause); - self.s.word(" "); + self.word(" "); self.bopen(); self.print_inner_attributes(&item.attrs); for trait_item in items { @@ -1360,7 +1360,7 @@ impl<'a> State<'a> { // FIXME(durka) this seems to be some quite outdated syntax for b in bounds.iter() { if let GenericBound::Trait(ref ptr, ast::TraitBoundModifier::Maybe) = *b { - self.s.space(); + self.space(); self.word_space("for ?"); self.print_trait_ref(&ptr.trait_ref); } else { @@ -1370,12 +1370,12 @@ impl<'a> State<'a> { self.nbsp(); self.print_type_bounds("=", &real_bounds[..]); self.print_where_clause(&generics.where_clause); - self.s.word(";"); + self.word(";"); } ast::ItemKind::MacCall(ref mac) => { self.print_mac(mac); if mac.args.need_semicolon() { - self.s.word(";"); + self.word(";"); } } ast::ItemKind::MacroDef(ref macro_def) => { @@ -1393,7 +1393,7 @@ impl<'a> State<'a> { fn print_formal_generic_params(&mut self, generic_params: &[ast::GenericParam]) { if !generic_params.is_empty() { - self.s.word("for"); + self.word("for"); self.print_generic_params(generic_params); self.nbsp(); } @@ -1416,7 +1416,7 @@ impl<'a> State<'a> { self.print_ident(ident); self.print_generic_params(&generics.params); self.print_where_clause(&generics.where_clause); - self.s.space(); + self.space(); self.print_variants(&enum_definition.variants, span) } @@ -1428,7 +1428,7 @@ impl<'a> State<'a> { self.print_outer_attributes(&v.attrs); self.ibox(INDENT_UNIT); self.print_variant(v); - self.s.word(","); + self.word(","); self.end(); self.maybe_print_trailing_comment(v.span, None); } @@ -1477,7 +1477,7 @@ impl<'a> State<'a> { self.print_ident(field.ident.unwrap()); self.word_nbsp(":"); self.print_type(&field.ty); - self.s.word(","); + self.word(","); } } @@ -1508,7 +1508,7 @@ impl<'a> State<'a> { } self.print_where_clause(&generics.where_clause); if print_finalizer { - self.s.word(";"); + self.word(";"); } self.end(); self.end(); // Close the outer-box. @@ -1526,7 +1526,7 @@ impl<'a> State<'a> { let generics = ast::Generics::default(); self.print_struct(&v.data, &generics, v.ident, v.span, false); if let Some(ref d) = v.disr_expr { - self.s.space(); + self.space(); self.word_space("="); self.print_expr(&d.value) } @@ -1558,7 +1558,7 @@ impl<'a> State<'a> { ast::AssocItemKind::MacCall(m) => { self.print_mac(m); if m.args.need_semicolon() { - self.s.word(";"); + self.word(";"); } } } @@ -1584,11 +1584,11 @@ impl<'a> State<'a> { if let Some(els) = els { self.cbox(INDENT_UNIT); self.ibox(INDENT_UNIT); - self.s.word(" else "); + self.word(" else "); self.print_block(els); } } - self.s.word(";"); + self.word(";"); self.end(); // `let` ibox } ast::StmtKind::Item(ref item) => self.print_item(item), @@ -1596,24 +1596,24 @@ impl<'a> State<'a> { self.space_if_not_bol(); self.print_expr_outer_attr_style(expr, false); if classify::expr_requires_semi_to_be_stmt(expr) { - self.s.word(";"); + self.word(";"); } } ast::StmtKind::Semi(ref expr) => { self.space_if_not_bol(); self.print_expr_outer_attr_style(expr, false); - self.s.word(";"); + self.word(";"); } ast::StmtKind::Empty => { self.space_if_not_bol(); - self.s.word(";"); + self.word(";"); } ast::StmtKind::MacCall(ref mac) => { self.space_if_not_bol(); self.print_outer_attributes(&mac.attrs); self.print_mac(&mac.mac); if mac.style == ast::MacStmtStyle::Semicolon { - self.s.word(";"); + self.word(";"); } } } @@ -1667,9 +1667,9 @@ impl<'a> State<'a> { /// Print a `let pat = expr` expression. crate fn print_let(&mut self, pat: &ast::Pat, expr: &ast::Expr) { - self.s.word("let "); + self.word("let "); self.print_pat(pat); - self.s.space(); + self.space(); self.word_space("="); let npals = || parser::needs_par_as_let_scrutinee(expr.precedence().order()); self.print_expr_cond_paren(expr, Self::cond_needs_par(expr) || npals()) @@ -1682,9 +1682,9 @@ impl<'a> State<'a> { ast::ExprKind::If(ref i, ref then, ref e) => { self.cbox(INDENT_UNIT - 1); self.ibox(0); - self.s.word(" else if "); + self.word(" else if "); self.print_expr_as_cond(i); - self.s.space(); + self.space(); self.print_block(then); self.print_else(e.as_deref()) } @@ -1692,7 +1692,7 @@ impl<'a> State<'a> { ast::ExprKind::Block(ref b, _) => { self.cbox(INDENT_UNIT - 1); self.ibox(0); - self.s.word(" else "); + self.word(" else "); self.print_block(b) } // Constraints would be great here! @@ -1706,7 +1706,7 @@ impl<'a> State<'a> { crate fn print_if(&mut self, test: &ast::Expr, blk: &ast::Block, elseopt: Option<&ast::Expr>) { self.head("if"); self.print_expr_as_cond(test); - self.s.space(); + self.space(); self.print_block(blk); self.print_else(elseopt) } @@ -1763,26 +1763,26 @@ impl<'a> State<'a> { fn print_expr_vec(&mut self, exprs: &[P]) { self.ibox(INDENT_UNIT); - self.s.word("["); + self.word("["); self.commasep_exprs(Inconsistent, exprs); - self.s.word("]"); + self.word("]"); self.end(); } fn print_expr_anon_const(&mut self, expr: &ast::AnonConst) { self.ibox(INDENT_UNIT); - self.s.word("const"); + self.word("const"); self.print_expr(&expr.value); self.end(); } fn print_expr_repeat(&mut self, element: &ast::Expr, count: &ast::AnonConst) { self.ibox(INDENT_UNIT); - self.s.word("["); + self.word("["); self.print_expr(element); self.word_space(";"); self.print_expr(&count.value); - self.s.word("]"); + self.word("]"); self.end(); } @@ -1798,7 +1798,7 @@ impl<'a> State<'a> { } else { self.print_path(path, true, 0); } - self.s.word("{"); + self.word("{"); self.commasep_cmnt( Consistent, fields, @@ -1818,26 +1818,26 @@ impl<'a> State<'a> { ast::StructRest::Base(_) | ast::StructRest::Rest(_) => { self.ibox(INDENT_UNIT); if !fields.is_empty() { - self.s.word(","); - self.s.space(); + self.word(","); + self.space(); } - self.s.word(".."); + self.word(".."); if let ast::StructRest::Base(ref expr) = *rest { self.print_expr(expr); } self.end(); } - ast::StructRest::None if !fields.is_empty() => self.s.word(","), + ast::StructRest::None if !fields.is_empty() => self.word(","), _ => {} } - self.s.word("}"); + self.word("}"); } fn print_expr_tup(&mut self, exprs: &[P]) { self.popen(); self.commasep_exprs(Inconsistent, exprs); if exprs.len() == 1 { - self.s.word(","); + self.word(","); } self.pclose() } @@ -1855,7 +1855,7 @@ impl<'a> State<'a> { fn print_expr_method_call(&mut self, segment: &ast::PathSegment, args: &[P]) { let base_args = &args[1..]; self.print_expr_maybe_paren(&args[0], parser::PREC_POSTFIX); - self.s.word("."); + self.word("."); self.print_ident(segment.ident); if let Some(ref args) = segment.args { self.print_generic_args(args, true); @@ -1896,13 +1896,13 @@ impl<'a> State<'a> { }; self.print_expr_maybe_paren(lhs, left_prec); - self.s.space(); + self.space(); self.word_space(op.node.to_string()); self.print_expr_maybe_paren(rhs, right_prec) } fn print_expr_unary(&mut self, op: ast::UnOp, expr: &ast::Expr) { - self.s.word(ast::UnOp::to_string(op)); + self.word(ast::UnOp::to_string(op)); self.print_expr_maybe_paren(expr, parser::PREC_PREFIX) } @@ -1912,7 +1912,7 @@ impl<'a> State<'a> { mutability: ast::Mutability, expr: &ast::Expr, ) { - self.s.word("&"); + self.word("&"); match kind { ast::BorrowKind::Ref => self.print_mutability(mutability, false), ast::BorrowKind::Raw => { @@ -1980,7 +1980,7 @@ impl<'a> State<'a> { ast::ExprKind::Cast(ref expr, ref ty) => { let prec = AssocOp::As.precedence() as i8; self.print_expr_maybe_paren(expr, prec); - self.s.space(); + self.space(); self.word_space("as"); self.print_type(ty); } @@ -2003,7 +2003,7 @@ impl<'a> State<'a> { } self.head("while"); self.print_expr_as_cond(test); - self.s.space(); + self.space(); self.print_block_with_attrs(blk, attrs); } ast::ExprKind::ForLoop(ref pat, ref iter, ref blk, opt_label) => { @@ -2013,10 +2013,10 @@ impl<'a> State<'a> { } self.head("for"); self.print_pat(pat); - self.s.space(); + self.space(); self.word_space("in"); self.print_expr_as_cond(iter); - self.s.space(); + self.space(); self.print_block_with_attrs(blk, attrs); } ast::ExprKind::Loop(ref blk, opt_label) => { @@ -2032,7 +2032,7 @@ impl<'a> State<'a> { self.ibox(INDENT_UNIT); self.word_nbsp("match"); self.print_expr_as_cond(expr); - self.s.space(); + self.space(); self.bopen(); self.print_inner_attributes_no_trailing_hardbreak(attrs); for arm in arms { @@ -2054,7 +2054,7 @@ impl<'a> State<'a> { self.print_capture_clause(capture_clause); self.print_fn_params_and_ret(decl, true); - self.s.space(); + self.space(); self.print_expr(body); self.end(); // need to close a box @@ -2084,33 +2084,33 @@ impl<'a> State<'a> { } ast::ExprKind::Await(ref expr) => { self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX); - self.s.word(".await"); + self.word(".await"); } ast::ExprKind::Assign(ref lhs, ref rhs, _) => { let prec = AssocOp::Assign.precedence() as i8; self.print_expr_maybe_paren(lhs, prec + 1); - self.s.space(); + self.space(); self.word_space("="); self.print_expr_maybe_paren(rhs, prec); } ast::ExprKind::AssignOp(op, ref lhs, ref rhs) => { let prec = AssocOp::Assign.precedence() as i8; self.print_expr_maybe_paren(lhs, prec + 1); - self.s.space(); - self.s.word(op.node.to_string()); + self.space(); + self.word(op.node.to_string()); self.word_space("="); self.print_expr_maybe_paren(rhs, prec); } ast::ExprKind::Field(ref expr, ident) => { self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX); - self.s.word("."); + self.word("."); self.print_ident(ident); } ast::ExprKind::Index(ref expr, ref index) => { self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX); - self.s.word("["); + self.word("["); self.print_expr(index); - self.s.word("]"); + self.word("]"); } ast::ExprKind::Range(ref start, ref end, limits) => { // Special case for `Range`. `AssocOp` claims that `Range` has higher precedence @@ -2122,41 +2122,41 @@ impl<'a> State<'a> { self.print_expr_maybe_paren(e, fake_prec); } if limits == ast::RangeLimits::HalfOpen { - self.s.word(".."); + self.word(".."); } else { - self.s.word("..="); + self.word("..="); } if let Some(ref e) = *end { self.print_expr_maybe_paren(e, fake_prec); } } - ast::ExprKind::Underscore => self.s.word("_"), + ast::ExprKind::Underscore => self.word("_"), ast::ExprKind::Path(None, ref path) => self.print_path(path, true, 0), ast::ExprKind::Path(Some(ref qself), ref path) => self.print_qpath(path, qself, true), ast::ExprKind::Break(opt_label, ref opt_expr) => { - self.s.word("break"); - self.s.space(); + self.word("break"); + self.space(); if let Some(label) = opt_label { self.print_ident(label.ident); - self.s.space(); + self.space(); } if let Some(ref expr) = *opt_expr { self.print_expr_maybe_paren(expr, parser::PREC_JUMP); - self.s.space(); + self.space(); } } ast::ExprKind::Continue(opt_label) => { - self.s.word("continue"); - self.s.space(); + self.word("continue"); + self.space(); if let Some(label) = opt_label { self.print_ident(label.ident); - self.s.space() + self.space() } } ast::ExprKind::Ret(ref result) => { - self.s.word("return"); + self.word("return"); if let Some(ref expr) = *result { - self.s.word(" "); + self.word(" "); self.print_expr_maybe_paren(expr, parser::PREC_JUMP); } } @@ -2165,7 +2165,7 @@ impl<'a> State<'a> { self.print_inline_asm(a); } ast::ExprKind::LlvmInlineAsm(ref a) => { - self.s.word("llvm_asm!"); + self.word("llvm_asm!"); self.popen(); self.print_symbol(a.asm, a.asm_str_style); self.word_space(":"); @@ -2183,7 +2183,7 @@ impl<'a> State<'a> { s.print_expr(&out.expr); s.pclose(); }); - self.s.space(); + self.space(); self.word_space(":"); self.commasep(Inconsistent, &a.inputs, |s, &(co, ref o)| { @@ -2192,7 +2192,7 @@ impl<'a> State<'a> { s.print_expr(o); s.pclose(); }); - self.s.space(); + self.space(); self.word_space(":"); self.commasep(Inconsistent, &a.clobbers, |s, &co| { @@ -2211,7 +2211,7 @@ impl<'a> State<'a> { } if !options.is_empty() { - self.s.space(); + self.space(); self.word_space(":"); self.commasep(Inconsistent, &options, |s, &co| { s.print_string(co, ast::StrStyle::Cooked); @@ -2227,25 +2227,25 @@ impl<'a> State<'a> { self.pclose(); } ast::ExprKind::Yield(ref e) => { - self.s.word("yield"); + self.word("yield"); if let Some(ref expr) = *e { - self.s.space(); + self.space(); self.print_expr_maybe_paren(expr, parser::PREC_JUMP); } } ast::ExprKind::Try(ref e) => { self.print_expr_maybe_paren(e, parser::PREC_POSTFIX); - self.s.word("?") + self.word("?") } ast::ExprKind::TryBlock(ref blk) => { self.head("try"); - self.s.space(); + self.space(); self.print_block_with_attrs(blk, attrs) } ast::ExprKind::Err => { self.popen(); - self.s.word("/*ERROR*/"); + self.word("/*ERROR*/"); self.pclose() } } @@ -2387,22 +2387,22 @@ impl<'a> State<'a> { } crate fn print_name(&mut self, name: Symbol) { - self.s.word(name.to_string()); + self.word(name.to_string()); self.ann.post(self, AnnNode::Name(&name)) } fn print_qpath(&mut self, path: &ast::Path, qself: &ast::QSelf, colons_before_params: bool) { - self.s.word("<"); + self.word("<"); self.print_type(&qself.ty); if qself.position > 0 { - self.s.space(); + self.space(); self.word_space("as"); let depth = path.segments.len() - qself.position; self.print_path(path, false, depth); } - self.s.word(">"); + self.word(">"); for item_segment in &path.segments[qself.position..] { - self.s.word("::"); + self.word("::"); self.print_ident(item_segment.ident); if let Some(ref args) = item_segment.args { self.print_generic_args(args, colons_before_params) @@ -2416,7 +2416,7 @@ impl<'a> State<'a> { /* Pat isn't normalized, but the beauty of it is that it doesn't matter */ match pat.kind { - PatKind::Wild => self.s.word("_"), + PatKind::Wild => self.word("_"), PatKind::Ident(binding_mode, ident, ref sub) => { match binding_mode { ast::BindingMode::ByRef(mutbl) => { @@ -2430,8 +2430,8 @@ impl<'a> State<'a> { } self.print_ident(ident); if let Some(ref p) = *sub { - self.s.space(); - self.s.word_space("@"); + self.space(); + self.word_space("@"); self.print_pat(p); } } @@ -2480,27 +2480,27 @@ impl<'a> State<'a> { if !fields.is_empty() { self.word_space(","); } - self.s.word(".."); + self.word(".."); } - self.s.space(); - self.s.word("}"); + self.space(); + self.word("}"); } PatKind::Tuple(ref elts) => { self.popen(); self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(p)); if elts.len() == 1 { - self.s.word(","); + self.word(","); } self.pclose(); } PatKind::Box(ref inner) => { - self.s.word("box "); + self.word("box "); self.print_pat(inner); } PatKind::Ref(ref inner, mutbl) => { - self.s.word("&"); + self.word("&"); if mutbl == ast::Mutability::Mut { - self.s.word("mut "); + self.word("mut "); } if let PatKind::Ident(ast::BindingMode::ByValue(ast::Mutability::Mut), ..) = inner.kind @@ -2516,23 +2516,23 @@ impl<'a> State<'a> { PatKind::Range(ref begin, ref end, Spanned { node: ref end_kind, .. }) => { if let Some(e) = begin { self.print_expr(e); - self.s.space(); + self.space(); } match *end_kind { - RangeEnd::Included(RangeSyntax::DotDotDot) => self.s.word("..."), - RangeEnd::Included(RangeSyntax::DotDotEq) => self.s.word("..="), - RangeEnd::Excluded => self.s.word(".."), + RangeEnd::Included(RangeSyntax::DotDotDot) => self.word("..."), + RangeEnd::Included(RangeSyntax::DotDotEq) => self.word("..="), + RangeEnd::Excluded => self.word(".."), } if let Some(e) = end { self.print_expr(e); } } PatKind::Slice(ref elts) => { - self.s.word("["); + self.word("["); self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(p)); - self.s.word("]"); + self.word("]"); } - PatKind::Rest => self.s.word(".."), + PatKind::Rest => self.word(".."), PatKind::Paren(ref inner) => { self.popen(); self.print_pat(inner); @@ -2546,18 +2546,18 @@ impl<'a> State<'a> { fn print_arm(&mut self, arm: &ast::Arm) { // Note, I have no idea why this check is necessary, but here it is. if arm.attrs.is_empty() { - self.s.space(); + self.space(); } self.cbox(INDENT_UNIT); self.ibox(0); self.maybe_print_comment(arm.pat.span.lo()); self.print_outer_attributes(&arm.attrs); self.print_pat(&arm.pat); - self.s.space(); + self.space(); if let Some(ref e) = arm.guard { self.word_space("if"); self.print_expr(e); - self.s.space(); + self.space(); } self.word_space("=>"); @@ -2573,13 +2573,13 @@ impl<'a> State<'a> { // If it is a user-provided unsafe block, print a comma after it. if let BlockCheckMode::Unsafe(ast::UserProvided) = blk.rules { - self.s.word(","); + self.word(","); } } _ => { self.end(); // Close the ibox for the pattern. self.print_expr(&arm.body); - self.s.word(","); + self.word(","); } } self.end(); // Close enclosing cbox. @@ -2589,17 +2589,17 @@ impl<'a> State<'a> { match explicit_self.node { SelfKind::Value(m) => { self.print_mutability(m, false); - self.s.word("self") + self.word("self") } SelfKind::Region(ref lt, m) => { - self.s.word("&"); + self.word("&"); self.print_opt_lifetime(lt); self.print_mutability(m, false); - self.s.word("self") + self.word("self") } SelfKind::Explicit(ref typ, m) => { self.print_mutability(m, false); - self.s.word("self"); + self.word("self"); self.word_space(":"); self.print_type(typ) } @@ -2626,7 +2626,7 @@ impl<'a> State<'a> { self.nbsp(); self.print_block_with_attrs(body, attrs); } else { - self.s.word(";"); + self.word(";"); } } @@ -2677,7 +2677,7 @@ impl<'a> State<'a> { pub fn print_type_bounds(&mut self, prefix: &'static str, bounds: &[ast::GenericBound]) { if !bounds.is_empty() { - self.s.word(prefix); + self.word(prefix); let mut first = true; for bound in bounds { if !(first && prefix.is_empty()) { @@ -2692,7 +2692,7 @@ impl<'a> State<'a> { match bound { GenericBound::Trait(tref, modifier) => { if modifier == &TraitBoundModifier::Maybe { - self.s.word("?"); + self.word("?"); } self.print_poly_trait_ref(tref); } @@ -2713,10 +2713,10 @@ impl<'a> State<'a> { ) { self.print_lifetime(lifetime); if !bounds.is_empty() { - self.s.word(": "); + self.word(": "); for (i, bound) in bounds.iter().enumerate() { if i != 0 { - self.s.word(" + "); + self.word(" + "); } match bound { ast::GenericBound::Outlives(lt) => self.print_lifetime(*lt), @@ -2731,7 +2731,7 @@ impl<'a> State<'a> { return; } - self.s.word("<"); + self.word("<"); self.commasep(Inconsistent, &generic_params, |s, param| { s.print_outer_attributes_inline(¶m.attrs); @@ -2745,7 +2745,7 @@ impl<'a> State<'a> { s.print_ident(param.ident); s.print_type_bounds(":", ¶m.bounds); if let Some(ref default) = default { - s.s.space(); + s.space(); s.word_space("="); s.print_type(default) } @@ -2753,12 +2753,12 @@ impl<'a> State<'a> { ast::GenericParamKind::Const { ref ty, kw_span: _, ref default } => { s.word_space("const"); s.print_ident(param.ident); - s.s.space(); + s.space(); s.word_space(":"); s.print_type(ty); s.print_type_bounds(":", ¶m.bounds); if let Some(ref default) = default { - s.s.space(); + s.space(); s.word_space("="); s.print_expr(&default.value); } @@ -2766,7 +2766,7 @@ impl<'a> State<'a> { } }); - self.s.word(">"); + self.word(">"); } crate fn print_where_clause(&mut self, where_clause: &ast::WhereClause) { @@ -2774,7 +2774,7 @@ impl<'a> State<'a> { return; } - self.s.space(); + self.space(); self.word_space("where"); for (i, predicate) in where_clause.predicates.iter().enumerate() { @@ -2806,7 +2806,7 @@ impl<'a> State<'a> { .. }) => { self.print_type(lhs_ty); - self.s.space(); + self.space(); self.word_space("="); self.print_type(rhs_ty); } @@ -2819,7 +2819,7 @@ impl<'a> State<'a> { ast::UseTreeKind::Simple(rename, ..) => { self.print_path(&tree.prefix, false, 0); if let Some(rename) = rename { - self.s.space(); + self.space(); self.word_space("as"); self.print_ident(rename); } @@ -2827,21 +2827,21 @@ impl<'a> State<'a> { ast::UseTreeKind::Glob => { if !tree.prefix.segments.is_empty() { self.print_path(&tree.prefix, false, 0); - self.s.word("::"); + self.word("::"); } - self.s.word("*"); + self.word("*"); } ast::UseTreeKind::Nested(ref items) => { if tree.prefix.segments.is_empty() { - self.s.word("{"); + self.word("{"); } else { self.print_path(&tree.prefix, false, 0); - self.s.word("::{"); + self.word("::{"); } self.commasep(Inconsistent, &items[..], |this, &(ref tree, _)| { this.print_use_tree(tree) }); - self.s.word("}"); + self.word("}"); } } } @@ -2880,8 +2880,8 @@ impl<'a> State<'a> { }; if !invalid { self.print_pat(&input.pat); - self.s.word(":"); - self.s.space(); + self.word(":"); + self.space(); } self.print_type(&input.ty); } @@ -2911,7 +2911,7 @@ impl<'a> State<'a> { ) { self.ibox(INDENT_UNIT); if !generic_params.is_empty() { - self.s.word("for"); + self.word("for"); self.print_generic_params(generic_params); } let generics = ast::Generics { @@ -2945,7 +2945,7 @@ impl<'a> State<'a> { } } - self.s.word("fn") + self.word("fn") } crate fn print_unsafety(&mut self, s: ast::Unsafe) { diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 6b1ef598b4553..4240a4045a1ec 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -89,7 +89,7 @@ impl<'a> State<'a> { Node::TraitRef(a) => self.print_trait_ref(&a), Node::Binding(a) | Node::Pat(a) => self.print_pat(&a), Node::Arm(a) => self.print_arm(&a), - Node::Infer(_) => self.s.word("_"), + Node::Infer(_) => self.word("_"), Node::Block(a) => { // Containing cbox, will be closed by print-block at `}`. self.cbox(INDENT_UNIT); @@ -130,7 +130,7 @@ impl<'a> PrintState<'a> for State<'a> { } fn print_ident(&mut self, ident: Ident) { - self.s.word(IdentPrinter::for_ast_ident(ident, ident.is_raw_guess()).to_string()); + self.word(IdentPrinter::for_ast_ident(ident, ident.is_raw_guess()).to_string()); self.ann.post(self, AnnNode::Name(&ident.name)) } @@ -194,7 +194,7 @@ where pub fn visibility_qualified>>(vis: &hir::Visibility<'_>, w: S) -> String { to_string(NO_ANN, |s| { s.print_visibility(vis); - s.s.word(w) + s.word(w) }) } @@ -244,7 +244,7 @@ impl<'a> State<'a> { pub fn bclose_maybe_open(&mut self, span: rustc_span::Span, close_box: bool) { self.maybe_print_comment(span.hi()); self.break_offset_if_not_bol(1, -(INDENT_UNIT as isize)); - self.s.word("}"); + self.word("}"); if close_box { self.end(); // close the outer-box } @@ -267,7 +267,7 @@ impl<'a> State<'a> { op(self, elt); i += 1; if i < len { - self.s.word(","); + self.word(","); self.maybe_print_trailing_comment(get_span(elt), Some(get_span(&elts[i]).hi())); self.space_if_not_bol(); } @@ -298,27 +298,27 @@ impl<'a> State<'a> { self.ibox(0); match ty.kind { hir::TyKind::Slice(ref ty) => { - self.s.word("["); + self.word("["); self.print_type(&ty); - self.s.word("]"); + self.word("]"); } hir::TyKind::Ptr(ref mt) => { - self.s.word("*"); + self.word("*"); self.print_mt(mt, true); } hir::TyKind::Rptr(ref lifetime, ref mt) => { - self.s.word("&"); + self.word("&"); self.print_opt_lifetime(lifetime); self.print_mt(mt, false); } hir::TyKind::Never => { - self.s.word("!"); + self.word("!"); } hir::TyKind::Tup(ref elts) => { self.popen(); self.commasep(Inconsistent, &elts[..], |s, ty| s.print_type(&ty)); if elts.len() == 1 { - self.s.word(","); + self.word(","); } self.pclose(); } @@ -332,7 +332,7 @@ impl<'a> State<'a> { f.param_names, ); } - hir::TyKind::OpaqueDef(..) => self.s.word("/*impl Trait*/"), + hir::TyKind::OpaqueDef(..) => self.word("/*impl Trait*/"), hir::TyKind::Path(ref qpath) => self.print_qpath(qpath, false), hir::TyKind::TraitObject(bounds, ref lifetime, syntax) => { if syntax == ast::TraitObjectSyntax::Dyn { @@ -355,24 +355,24 @@ impl<'a> State<'a> { } } hir::TyKind::Array(ref ty, ref length) => { - self.s.word("["); + self.word("["); self.print_type(&ty); - self.s.word("; "); + self.word("; "); self.print_anon_const(length); - self.s.word("]"); + self.word("]"); } hir::TyKind::Typeof(ref e) => { - self.s.word("typeof("); + self.word("typeof("); self.print_anon_const(e); - self.s.word(")"); + self.word(")"); } hir::TyKind::Err => { self.popen(); - self.s.word("/*ERROR*/"); + self.word("/*ERROR*/"); self.pclose(); } hir::TyKind::Infer => { - self.s.word("_"); + self.word("_"); } } self.end() @@ -400,7 +400,7 @@ impl<'a> State<'a> { None, ); self.end(); // end head-ibox - self.s.word(";"); + self.word(";"); self.end() // end the outer fn box } hir::ForeignItemKind::Static(ref t, m) => { @@ -411,14 +411,14 @@ impl<'a> State<'a> { self.print_ident(item.ident); self.word_space(":"); self.print_type(&t); - self.s.word(";"); + self.word(";"); self.end(); // end the head-ibox self.end() // end the outer cbox } hir::ForeignItemKind::Type => { self.head(visibility_qualified(&item.vis, "type")); self.print_ident(item.ident); - self.s.word(";"); + self.word(";"); self.end(); // end the head-ibox self.end() // end the outer cbox } @@ -432,17 +432,17 @@ impl<'a> State<'a> { default: Option, vis: &hir::Visibility<'_>, ) { - self.s.word(visibility_qualified(vis, "")); + self.word(visibility_qualified(vis, "")); self.word_space("const"); self.print_ident(ident); self.word_space(":"); self.print_type(ty); if let Some(expr) = default { - self.s.space(); + self.space(); self.word_space("="); self.ann.nested(self, Nested::Body(expr)); } - self.s.word(";") + self.word(";") } fn print_associated_type( @@ -460,11 +460,11 @@ impl<'a> State<'a> { } self.print_where_clause(&generics.where_clause); if let Some(ty) = ty { - self.s.space(); + self.space(); self.word_space("="); self.print_type(ty); } - self.s.word(";") + self.word(";") } fn print_item_type( @@ -479,9 +479,9 @@ impl<'a> State<'a> { self.end(); // end the inner ibox self.print_where_clause(&generics.where_clause); - self.s.space(); + self.space(); inner(self); - self.s.word(";"); + self.word(";"); self.end(); // end the outer ibox } @@ -497,12 +497,12 @@ impl<'a> State<'a> { self.head(visibility_qualified(&item.vis, "extern crate")); if let Some(orig_name) = orig_name { self.print_name(orig_name); - self.s.space(); - self.s.word("as"); - self.s.space(); + self.space(); + self.word("as"); + self.space(); } self.print_ident(item.ident); - self.s.word(";"); + self.word(";"); self.end(); // end inner head-block self.end(); // end outer head-block } @@ -513,14 +513,14 @@ impl<'a> State<'a> { match kind { hir::UseKind::Single => { if path.segments.last().unwrap().ident != item.ident { - self.s.space(); + self.space(); self.word_space("as"); self.print_ident(item.ident); } - self.s.word(";"); + self.word(";"); } - hir::UseKind::Glob => self.s.word("::*;"), - hir::UseKind::ListStem => self.s.word("::{};"), + hir::UseKind::Glob => self.word("::*;"), + hir::UseKind::ListStem => self.word("::{};"), } self.end(); // end inner head-block self.end(); // end outer head-block @@ -533,12 +533,12 @@ impl<'a> State<'a> { self.print_ident(item.ident); self.word_space(":"); self.print_type(&ty); - self.s.space(); + self.space(); self.end(); // end the head-ibox self.word_space("="); self.ann.nested(self, Nested::Body(expr)); - self.s.word(";"); + self.word(";"); self.end(); // end the outer cbox } hir::ItemKind::Const(ref ty, expr) => { @@ -546,12 +546,12 @@ impl<'a> State<'a> { self.print_ident(item.ident); self.word_space(":"); self.print_type(&ty); - self.s.space(); + self.space(); self.end(); // end the head-ibox self.word_space("="); self.ann.nested(self, Nested::Body(expr)); - self.s.word(";"); + self.word(";"); self.end(); // end the outer cbox } hir::ItemKind::Fn(ref sig, ref param_names, body) => { @@ -565,7 +565,7 @@ impl<'a> State<'a> { &[], Some(body), ); - self.s.word(" "); + self.word(" "); self.end(); // need to close a box self.end(); // need to close a box self.ann.nested(self, Nested::Body(body)); @@ -609,7 +609,7 @@ impl<'a> State<'a> { let mut real_bounds = Vec::with_capacity(opaque_ty.bounds.len()); for b in opaque_ty.bounds.iter() { if let GenericBound::Trait(ref ptr, hir::TraitBoundModifier::Maybe) = *b { - state.s.space(); + state.space(); state.word_space("for ?"); state.print_trait_ref(&ptr.trait_ref); } else { @@ -649,7 +649,7 @@ impl<'a> State<'a> { if !generics.params.is_empty() { self.print_generic_params(&generics.params); - self.s.space(); + self.space(); } if constness == hir::Constness::Const { @@ -657,19 +657,19 @@ impl<'a> State<'a> { } if let hir::ImplPolarity::Negative(_) = polarity { - self.s.word("!"); + self.word("!"); } if let Some(ref t) = of_trait { self.print_trait_ref(t); - self.s.space(); + self.space(); self.word_space("for"); } self.print_type(&self_ty); self.print_where_clause(&generics.where_clause); - self.s.space(); + self.space(); self.bopen(); self.print_inner_attributes(attrs); for impl_item in items { @@ -688,7 +688,7 @@ impl<'a> State<'a> { let mut real_bounds = Vec::with_capacity(bounds.len()); for b in bounds.iter() { if let GenericBound::Trait(ref ptr, hir::TraitBoundModifier::Maybe) = *b { - self.s.space(); + self.space(); self.word_space("for ?"); self.print_trait_ref(&ptr.trait_ref); } else { @@ -697,7 +697,7 @@ impl<'a> State<'a> { } self.print_bounds(":", real_bounds); self.print_where_clause(&generics.where_clause); - self.s.word(" "); + self.word(" "); self.bopen(); for trait_item in trait_items { self.ann.nested(self, Nested::TraitItem(trait_item.id)); @@ -714,7 +714,7 @@ impl<'a> State<'a> { // FIXME(durka) this seems to be some quite outdated syntax for b in bounds.iter() { if let GenericBound::Trait(ref ptr, hir::TraitBoundModifier::Maybe) = *b { - self.s.space(); + self.space(); self.word_space("for ?"); self.print_trait_ref(&ptr.trait_ref); } else { @@ -724,7 +724,7 @@ impl<'a> State<'a> { self.nbsp(); self.print_bounds("=", real_bounds); self.print_where_clause(&generics.where_clause); - self.s.word(";"); + self.word(";"); } } self.ann.post(self, AnnNode::Item(item)) @@ -736,7 +736,7 @@ impl<'a> State<'a> { fn print_formal_generic_params(&mut self, generic_params: &[hir::GenericParam<'_>]) { if !generic_params.is_empty() { - self.s.word("for"); + self.word("for"); self.print_generic_params(generic_params); self.nbsp(); } @@ -759,7 +759,7 @@ impl<'a> State<'a> { self.print_name(name); self.print_generic_params(&generics.params); self.print_where_clause(&generics.where_clause); - self.s.space(); + self.space(); self.print_variants(&enum_definition.variants, span) } @@ -771,7 +771,7 @@ impl<'a> State<'a> { self.print_outer_attributes(self.attrs(v.id)); self.ibox(INDENT_UNIT); self.print_variant(v); - self.s.word(","); + self.word(","); self.end(); self.maybe_print_trailing_comment(v.span, None); } @@ -784,10 +784,10 @@ impl<'a> State<'a> { hir::VisibilityKind::Crate(ast::CrateSugar::JustCrate) => self.word_nbsp("crate"), hir::VisibilityKind::Crate(ast::CrateSugar::PubCrate) => self.word_nbsp("pub(crate)"), hir::VisibilityKind::Restricted { ref path, .. } => { - self.s.word("pub("); + self.word("pub("); if path.segments.len() == 1 && path.segments[0].ident.name == kw::Super { // Special case: `super` can print like `pub(super)`. - self.s.word("super"); + self.word("super"); } else { // Everything else requires `in` at present. self.word_nbsp("in"); @@ -830,7 +830,7 @@ impl<'a> State<'a> { } self.print_where_clause(&generics.where_clause); if print_finalizer { - self.s.word(";"); + self.word(";"); } self.end(); self.end() // close the outer-box @@ -849,7 +849,7 @@ impl<'a> State<'a> { self.print_ident(field.ident); self.word_nbsp(":"); self.print_type(&field.ty); - self.s.word(","); + self.word(","); } self.bclose(span) @@ -862,7 +862,7 @@ impl<'a> State<'a> { let generics = hir::Generics::empty(); self.print_struct(&v.data, &generics, v.ident.name, v.span, false); if let Some(ref d) = v.disr_expr { - self.s.space(); + self.space(); self.word_space("="); self.print_anon_const(d); } @@ -894,7 +894,7 @@ impl<'a> State<'a> { let vis = Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Inherited }; self.print_method_sig(ti.ident, sig, &ti.generics, &vis, arg_names, None); - self.s.word(";"); + self.word(";"); } hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => { let vis = @@ -975,11 +975,11 @@ impl<'a> State<'a> { hir::StmtKind::Semi(ref expr) => { self.space_if_not_bol(); self.print_expr(&expr); - self.s.word(";"); + self.word(";"); } } if stmt_ends_with_semi(&st.kind) { - self.s.word(";"); + self.word(";"); } self.maybe_print_trailing_comment(st.span, None) } @@ -1031,9 +1031,9 @@ impl<'a> State<'a> { hir::ExprKind::If(ref i, ref then, ref e) => { self.cbox(INDENT_UNIT - 1); self.ibox(0); - self.s.word(" else if "); + self.word(" else if "); self.print_expr_as_cond(&i); - self.s.space(); + self.space(); self.print_expr(&then); self.print_else(e.as_ref().map(|e| &**e)) } @@ -1041,7 +1041,7 @@ impl<'a> State<'a> { hir::ExprKind::Block(ref b, _) => { self.cbox(INDENT_UNIT - 1); self.ibox(0); - self.s.word(" else "); + self.word(" else "); self.print_block(&b) } // Constraints would be great here! @@ -1060,7 +1060,7 @@ impl<'a> State<'a> { ) { self.head("if"); self.print_expr_as_cond(test); - self.s.space(); + self.space(); self.print_expr(blk); self.print_else(elseopt) } @@ -1102,9 +1102,9 @@ impl<'a> State<'a> { /// Print a `let pat = expr` expression. fn print_let(&mut self, pat: &hir::Pat<'_>, expr: &hir::Expr<'_>) { - self.s.word("let "); + self.word("let "); self.print_pat(pat); - self.s.space(); + self.space(); self.word_space("="); let npals = || parser::needs_par_as_let_scrutinee(expr.precedence().order()); self.print_expr_cond_paren(expr, Self::cond_needs_par(expr) || npals()) @@ -1123,26 +1123,26 @@ impl<'a> State<'a> { fn print_expr_vec(&mut self, exprs: &[hir::Expr<'_>]) { self.ibox(INDENT_UNIT); - self.s.word("["); + self.word("["); self.commasep_exprs(Inconsistent, exprs); - self.s.word("]"); + self.word("]"); self.end() } fn print_expr_anon_const(&mut self, anon_const: &hir::AnonConst) { self.ibox(INDENT_UNIT); - self.s.word_space("const"); + self.word_space("const"); self.print_anon_const(anon_const); self.end() } fn print_expr_repeat(&mut self, element: &hir::Expr<'_>, count: &hir::AnonConst) { self.ibox(INDENT_UNIT); - self.s.word("["); + self.word("["); self.print_expr(element); self.word_space(";"); self.print_anon_const(count); - self.s.word("]"); + self.word("]"); self.end() } @@ -1153,7 +1153,7 @@ impl<'a> State<'a> { wth: &Option<&hir::Expr<'_>>, ) { self.print_qpath(qpath, true); - self.s.word("{"); + self.word("{"); self.commasep_cmnt( Consistent, fields, @@ -1172,27 +1172,27 @@ impl<'a> State<'a> { Some(ref expr) => { self.ibox(INDENT_UNIT); if !fields.is_empty() { - self.s.word(","); - self.s.space(); + self.word(","); + self.space(); } - self.s.word(".."); + self.word(".."); self.print_expr(&expr); self.end(); } _ => { if !fields.is_empty() { - self.s.word(",") + self.word(",") } } } - self.s.word("}"); + self.word("}"); } fn print_expr_tup(&mut self, exprs: &[hir::Expr<'_>]) { self.popen(); self.commasep_exprs(Inconsistent, exprs); if exprs.len() == 1 { - self.s.word(","); + self.word(","); } self.pclose() } @@ -1210,7 +1210,7 @@ impl<'a> State<'a> { fn print_expr_method_call(&mut self, segment: &hir::PathSegment<'_>, args: &[hir::Expr<'_>]) { let base_args = &args[1..]; self.print_expr_maybe_paren(&args[0], parser::PREC_POSTFIX); - self.s.word("."); + self.word("."); self.print_ident(segment.ident); let generic_args = segment.args(); @@ -1246,13 +1246,13 @@ impl<'a> State<'a> { }; self.print_expr_maybe_paren(lhs, left_prec); - self.s.space(); + self.space(); self.word_space(op.node.as_str()); self.print_expr_maybe_paren(rhs, right_prec) } fn print_expr_unary(&mut self, op: hir::UnOp, expr: &hir::Expr<'_>) { - self.s.word(op.as_str()); + self.word(op.as_str()); self.print_expr_maybe_paren(expr, parser::PREC_PREFIX) } @@ -1262,7 +1262,7 @@ impl<'a> State<'a> { mutability: hir::Mutability, expr: &hir::Expr<'_>, ) { - self.s.word("&"); + self.word("&"); match kind { hir::BorrowKind::Ref => self.print_mutability(mutability, false), hir::BorrowKind::Raw => { @@ -1434,7 +1434,7 @@ impl<'a> State<'a> { hir::ExprKind::Cast(ref expr, ref ty) => { let prec = AssocOp::As.precedence() as i8; self.print_expr_maybe_paren(&expr, prec); - self.s.space(); + self.space(); self.word_space("as"); self.print_type(&ty); } @@ -1453,7 +1453,7 @@ impl<'a> State<'a> { // Print `let _t = $init;`: let temp = Ident::from_str("_t"); self.print_local(Some(init), |this| this.print_ident(temp)); - self.s.word(";"); + self.word(";"); // Print `_t`: self.space_if_not_bol(); @@ -1481,7 +1481,7 @@ impl<'a> State<'a> { self.ibox(INDENT_UNIT); self.word_nbsp("match"); self.print_expr_as_cond(&expr); - self.s.space(); + self.space(); self.bopen(); for arm in arms { self.print_arm(arm); @@ -1492,7 +1492,7 @@ impl<'a> State<'a> { self.print_capture_clause(capture_clause); self.print_closure_params(&decl, body); - self.s.space(); + self.space(); // This is a bare expression. self.ann.nested(self, Nested::Body(body)); @@ -1517,54 +1517,54 @@ impl<'a> State<'a> { hir::ExprKind::Assign(ref lhs, ref rhs, _) => { let prec = AssocOp::Assign.precedence() as i8; self.print_expr_maybe_paren(&lhs, prec + 1); - self.s.space(); + self.space(); self.word_space("="); self.print_expr_maybe_paren(&rhs, prec); } hir::ExprKind::AssignOp(op, ref lhs, ref rhs) => { let prec = AssocOp::Assign.precedence() as i8; self.print_expr_maybe_paren(&lhs, prec + 1); - self.s.space(); - self.s.word(op.node.as_str()); + self.space(); + self.word(op.node.as_str()); self.word_space("="); self.print_expr_maybe_paren(&rhs, prec); } hir::ExprKind::Field(ref expr, ident) => { self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX); - self.s.word("."); + self.word("."); self.print_ident(ident); } hir::ExprKind::Index(ref expr, ref index) => { self.print_expr_maybe_paren(&expr, parser::PREC_POSTFIX); - self.s.word("["); + self.word("["); self.print_expr(&index); - self.s.word("]"); + self.word("]"); } hir::ExprKind::Path(ref qpath) => self.print_qpath(qpath, true), hir::ExprKind::Break(destination, ref opt_expr) => { - self.s.word("break"); - self.s.space(); + self.word("break"); + self.space(); if let Some(label) = destination.label { self.print_ident(label.ident); - self.s.space(); + self.space(); } if let Some(ref expr) = *opt_expr { self.print_expr_maybe_paren(expr, parser::PREC_JUMP); - self.s.space(); + self.space(); } } hir::ExprKind::Continue(destination) => { - self.s.word("continue"); - self.s.space(); + self.word("continue"); + self.space(); if let Some(label) = destination.label { self.print_ident(label.ident); - self.s.space() + self.space() } } hir::ExprKind::Ret(ref result) => { - self.s.word("return"); + self.word("return"); if let Some(ref expr) = *result { - self.s.word(" "); + self.word(" "); self.print_expr_maybe_paren(&expr, parser::PREC_JUMP); } } @@ -1574,7 +1574,7 @@ impl<'a> State<'a> { } hir::ExprKind::LlvmInlineAsm(ref a) => { let i = &a.inner; - self.s.word("llvm_asm!"); + self.word("llvm_asm!"); self.popen(); self.print_symbol(i.asm, i.asm_str_style); self.word_space(":"); @@ -1594,7 +1594,7 @@ impl<'a> State<'a> { s.pclose(); out_idx += 1; }); - self.s.space(); + self.space(); self.word_space(":"); let mut in_idx = 0; @@ -1605,7 +1605,7 @@ impl<'a> State<'a> { s.pclose(); in_idx += 1; }); - self.s.space(); + self.space(); self.word_space(":"); self.commasep(Inconsistent, &i.clobbers, |s, &co| { @@ -1624,7 +1624,7 @@ impl<'a> State<'a> { } if !options.is_empty() { - self.s.space(); + self.space(); self.word_space(":"); self.commasep(Inconsistent, &options, |s, &co| { s.print_string(co, ast::StrStyle::Cooked); @@ -1639,7 +1639,7 @@ impl<'a> State<'a> { } hir::ExprKind::Err => { self.popen(); - self.s.word("/*ERROR*/"); + self.word("/*ERROR*/"); self.pclose(); } } @@ -1664,7 +1664,7 @@ impl<'a> State<'a> { for (i, segment) in path.segments.iter().enumerate() { if i > 0 { - self.s.word("::") + self.word("::") } if segment.ident.name != kw::PathRoot { self.print_ident(segment.ident); @@ -1684,14 +1684,14 @@ impl<'a> State<'a> { match *qpath { hir::QPath::Resolved(None, ref path) => self.print_path(path, colons_before_params), hir::QPath::Resolved(Some(ref qself), ref path) => { - self.s.word("<"); + self.word("<"); self.print_type(qself); - self.s.space(); + self.space(); self.word_space("as"); for (i, segment) in path.segments[..path.segments.len() - 1].iter().enumerate() { if i > 0 { - self.s.word("::") + self.word("::") } if segment.ident.name != kw::PathRoot { self.print_ident(segment.ident); @@ -1703,8 +1703,8 @@ impl<'a> State<'a> { } } - self.s.word(">"); - self.s.word("::"); + self.word(">"); + self.word("::"); let item_segment = path.segments.last().unwrap(); self.print_ident(item_segment.ident); self.print_generic_args( @@ -1720,12 +1720,12 @@ impl<'a> State<'a> { if let hir::TyKind::Path(hir::QPath::Resolved(None, _)) = &qself.kind { self.print_type(qself); } else { - self.s.word("<"); + self.word("<"); self.print_type(qself); - self.s.word(">"); + self.word(">"); } - self.s.word("::"); + self.word("::"); self.print_ident(item_segment.ident); self.print_generic_args( item_segment.args(), @@ -1734,9 +1734,9 @@ impl<'a> State<'a> { ) } hir::QPath::LangItem(lang_item, span) => { - self.s.word("#[lang = \""); + self.word("#[lang = \""); self.print_ident(Ident::new(lang_item.name(), span)); - self.s.word("\"]"); + self.word("\"]"); } } } @@ -1748,9 +1748,9 @@ impl<'a> State<'a> { colons_before_params: bool, ) { if generic_args.parenthesized { - self.s.word("("); + self.word("("); self.commasep(Inconsistent, generic_args.inputs(), |s, ty| s.print_type(&ty)); - self.s.word(")"); + self.word(")"); self.space_if_not_bol(); self.word_space("->"); @@ -1761,7 +1761,7 @@ impl<'a> State<'a> { let start_or_comma = |this: &mut Self| { if empty.get() { empty.set(false); - this.s.word(start) + this.word(start) } else { this.word_space(",") } @@ -1795,14 +1795,14 @@ impl<'a> State<'a> { // "non-exhaustive patterns: `Some::<..>(_)` not covered"). if infer_args && false { start_or_comma(self); - self.s.word(".."); + self.word(".."); } for binding in generic_args.bindings.iter() { start_or_comma(self); self.print_ident(binding.ident); self.print_generic_args(binding.gen_args, false, false); - self.s.space(); + self.space(); match generic_args.bindings[0].kind { hir::TypeBindingKind::Equality { ref ty } => { self.word_space("="); @@ -1815,7 +1815,7 @@ impl<'a> State<'a> { } if !empty.get() { - self.s.word(">") + self.word(">") } } } @@ -1826,7 +1826,7 @@ impl<'a> State<'a> { // Pat isn't normalized, but the beauty of it // is that it doesn't matter match pat.kind { - PatKind::Wild => self.s.word("_"), + PatKind::Wild => self.word("_"), PatKind::Binding(binding_mode, _, ident, ref sub) => { match binding_mode { hir::BindingAnnotation::Ref => { @@ -1844,7 +1844,7 @@ impl<'a> State<'a> { } self.print_ident(ident); if let Some(ref p) = *sub { - self.s.word("@"); + self.word("@"); self.print_pat(&p); } } @@ -1856,9 +1856,9 @@ impl<'a> State<'a> { if ddpos != 0 { self.word_space(","); } - self.s.word(".."); + self.word(".."); if ddpos != elts.len() { - self.s.word(","); + self.word(","); self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(&p)); } } else { @@ -1891,10 +1891,10 @@ impl<'a> State<'a> { if !fields.is_empty() { self.word_space(","); } - self.s.word(".."); + self.word(".."); } - self.s.space(); - self.s.word("}"); + self.space(); + self.word("}"); } PatKind::Or(ref pats) => { self.strsep("|", true, Inconsistent, &pats[..], |s, p| s.print_pat(&p)); @@ -1906,22 +1906,22 @@ impl<'a> State<'a> { if ddpos != 0 { self.word_space(","); } - self.s.word(".."); + self.word(".."); if ddpos != elts.len() { - self.s.word(","); + self.word(","); self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(&p)); } } else { self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(&p)); if elts.len() == 1 { - self.s.word(","); + self.word(","); } } self.pclose(); } PatKind::Box(ref inner) => { let is_range_inner = matches!(inner.kind, PatKind::Range(..)); - self.s.word("box "); + self.word("box "); if is_range_inner { self.popen(); } @@ -1932,8 +1932,8 @@ impl<'a> State<'a> { } PatKind::Ref(ref inner, mutbl) => { let is_range_inner = matches!(inner.kind, PatKind::Range(..)); - self.s.word("&"); - self.s.word(mutbl.prefix_str()); + self.word("&"); + self.word(mutbl.prefix_str()); if is_range_inner { self.popen(); } @@ -1946,18 +1946,18 @@ impl<'a> State<'a> { PatKind::Range(ref begin, ref end, ref end_kind) => { if let Some(expr) = begin { self.print_expr(expr); - self.s.space(); + self.space(); } match *end_kind { - RangeEnd::Included => self.s.word("..."), - RangeEnd::Excluded => self.s.word(".."), + RangeEnd::Included => self.word("..."), + RangeEnd::Excluded => self.word(".."), } if let Some(expr) = end { self.print_expr(expr); } } PatKind::Slice(ref before, ref slice, ref after) => { - self.s.word("["); + self.word("["); self.commasep(Inconsistent, &before[..], |s, p| s.print_pat(&p)); if let Some(ref p) = *slice { if !before.is_empty() { @@ -1968,13 +1968,13 @@ impl<'a> State<'a> { } else { self.print_pat(&p); } - self.s.word(".."); + self.word(".."); if !after.is_empty() { self.word_space(","); } } self.commasep(Inconsistent, &after[..], |s, p| s.print_pat(&p)); - self.s.word("]"); + self.word("]"); } } self.ann.post(self, AnnNode::Pat(pat)) @@ -1989,29 +1989,29 @@ impl<'a> State<'a> { // I have no idea why this check is necessary, but here it // is :( if self.attrs(arm.hir_id).is_empty() { - self.s.space(); + self.space(); } self.cbox(INDENT_UNIT); self.ann.pre(self, AnnNode::Arm(arm)); self.ibox(0); self.print_outer_attributes(&self.attrs(arm.hir_id)); self.print_pat(&arm.pat); - self.s.space(); + self.space(); if let Some(ref g) = arm.guard { match g { hir::Guard::If(e) => { self.word_space("if"); self.print_expr(&e); - self.s.space(); + self.space(); } hir::Guard::IfLet(pat, e) => { self.word_nbsp("if"); self.word_nbsp("let"); self.print_pat(&pat); - self.s.space(); + self.space(); self.word_space("="); self.print_expr(&e); - self.s.space(); + self.space(); } } } @@ -2029,13 +2029,13 @@ impl<'a> State<'a> { // If it is a user-provided unsafe block, print a comma after it if let hir::BlockCheckMode::UnsafeBlock(hir::UnsafeSource::UserProvided) = blk.rules { - self.s.word(","); + self.word(","); } } _ => { self.end(); // close the ibox for the pattern self.print_expr(&arm.body); - self.s.word(","); + self.word(","); } } self.ann.post(self, AnnNode::Arm(arm)); @@ -2067,20 +2067,20 @@ impl<'a> State<'a> { self.commasep(Inconsistent, &decl.inputs, |s, ty| { s.ibox(INDENT_UNIT); if let Some(arg_name) = arg_names.get(i) { - s.s.word(arg_name.to_string()); - s.s.word(":"); - s.s.space(); + s.word(arg_name.to_string()); + s.word(":"); + s.space(); } else if let Some(body_id) = body_id { s.ann.nested(s, Nested::BodyParamPat(body_id, i)); - s.s.word(":"); - s.s.space(); + s.word(":"); + s.space(); } i += 1; s.print_type(ty); s.end() }); if decl.c_variadic { - self.s.word(", ..."); + self.word(", ..."); } self.pclose(); @@ -2089,7 +2089,7 @@ impl<'a> State<'a> { } fn print_closure_params(&mut self, decl: &hir::FnDecl<'_>, body_id: hir::BodyId) { - self.s.word("|"); + self.word("|"); let mut i = 0; self.commasep(Inconsistent, &decl.inputs, |s, ty| { s.ibox(INDENT_UNIT); @@ -2100,13 +2100,13 @@ impl<'a> State<'a> { if let hir::TyKind::Infer = ty.kind { // Print nothing. } else { - s.s.word(":"); - s.s.space(); + s.word(":"); + s.space(); s.print_type(ty); } s.end(); }); - self.s.word("|"); + self.word("|"); if let hir::FnRetTy::DefaultReturn(..) = decl.output { return; @@ -2138,7 +2138,7 @@ impl<'a> State<'a> { let mut first = true; for bound in bounds { if first { - self.s.word(prefix); + self.word(prefix); } if !(first && prefix.is_empty()) { self.nbsp(); @@ -2152,14 +2152,14 @@ impl<'a> State<'a> { match bound { GenericBound::Trait(tref, modifier) => { if modifier == &TraitBoundModifier::Maybe { - self.s.word("?"); + self.word("?"); } self.print_poly_trait_ref(tref); } GenericBound::LangItemTrait(lang_item, span, ..) => { - self.s.word("#[lang = \""); + self.word("#[lang = \""); self.print_ident(Ident::new(lang_item.name(), *span)); - self.s.word("\"]"); + self.word("\"]"); } GenericBound::Outlives(lt) => { self.print_lifetime(lt); @@ -2170,11 +2170,11 @@ impl<'a> State<'a> { pub fn print_generic_params(&mut self, generic_params: &[GenericParam<'_>]) { if !generic_params.is_empty() { - self.s.word("<"); + self.word("<"); self.commasep(Inconsistent, generic_params, |s, param| s.print_generic_param(param)); - self.s.word(">"); + self.word(">"); } } @@ -2191,7 +2191,7 @@ impl<'a> State<'a> { for bound in param.bounds { match bound { GenericBound::Outlives(ref lt) => { - self.s.word(sep); + self.word(sep); self.print_lifetime(lt); sep = "+"; } @@ -2202,7 +2202,7 @@ impl<'a> State<'a> { GenericParamKind::Type { ref default, .. } => { self.print_bounds(":", param.bounds); if let Some(default) = default { - self.s.space(); + self.space(); self.word_space("="); self.print_type(&default) } @@ -2211,7 +2211,7 @@ impl<'a> State<'a> { self.word_space(":"); self.print_type(ty); if let Some(ref default) = default { - self.s.space(); + self.space(); self.word_space("="); self.print_anon_const(&default) } @@ -2228,7 +2228,7 @@ impl<'a> State<'a> { return; } - self.s.space(); + self.space(); self.word_space("where"); for (i, predicate) in where_clause.predicates.iter().enumerate() { @@ -2253,7 +2253,7 @@ impl<'a> State<'a> { .. }) => { self.print_lifetime(lifetime); - self.s.word(":"); + self.word(":"); for (i, bound) in bounds.iter().enumerate() { match bound { @@ -2264,7 +2264,7 @@ impl<'a> State<'a> { } if i != 0 { - self.s.word(":"); + self.word(":"); } } } @@ -2272,7 +2272,7 @@ impl<'a> State<'a> { lhs_ty, rhs_ty, .. }) => { self.print_type(lhs_ty); - self.s.space(); + self.space(); self.word_space("="); self.print_type(rhs_ty); } @@ -2326,7 +2326,7 @@ impl<'a> State<'a> { ) { self.ibox(INDENT_UNIT); if !generic_params.is_empty() { - self.s.word("for"); + self.word("for"); self.print_generic_params(generic_params); } let generics = hir::Generics { @@ -2352,7 +2352,7 @@ impl<'a> State<'a> { } pub fn print_fn_header_info(&mut self, header: hir::FnHeader, vis: &hir::Visibility<'_>) { - self.s.word(visibility_qualified(vis, "")); + self.word(visibility_qualified(vis, "")); match header.constness { hir::Constness::NotConst => {} @@ -2371,7 +2371,7 @@ impl<'a> State<'a> { self.word_nbsp(header.abi.to_string()); } - self.s.word("fn") + self.word("fn") } pub fn print_unsafety(&mut self, s: hir::Unsafety) { From 6e7ec0c5b4b961a9260e72613b7d5477f09d7187 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Fri, 12 Nov 2021 14:45:19 +0100 Subject: [PATCH 16/20] Simplify collect_in_band_defs. --- compiler/rustc_ast_lowering/src/lib.rs | 71 +++++++++++++------------- 1 file changed, 35 insertions(+), 36 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index d0fbc2d0f11d4..ec5022679d439 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -646,31 +646,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { /// parameter while `f` is running (and restored afterwards). fn collect_in_band_defs( &mut self, - parent_def_id: LocalDefId, - anonymous_lifetime_mode: AnonymousLifetimeMode, - f: impl FnOnce(&mut Self) -> (Vec>, T), - ) -> (Vec>, T) { + f: impl FnOnce(&mut Self) -> T, + ) -> (Vec<(Span, ParamName)>, T) { assert!(!self.is_collecting_in_band_lifetimes); assert!(self.lifetimes_to_define.is_empty()); - let old_anonymous_lifetime_mode = self.anonymous_lifetime_mode; - - self.anonymous_lifetime_mode = anonymous_lifetime_mode; self.is_collecting_in_band_lifetimes = true; - let (in_band_ty_params, res) = f(self); + let res = f(self); self.is_collecting_in_band_lifetimes = false; - self.anonymous_lifetime_mode = old_anonymous_lifetime_mode; - - let lifetimes_to_define = self.lifetimes_to_define.split_off(0); - let params = lifetimes_to_define - .into_iter() - .map(|(span, hir_name)| self.lifetime_to_generic_param(span, hir_name, parent_def_id)) - .chain(in_band_ty_params.into_iter()) - .collect(); - - (params, res) + let lifetimes_to_define = std::mem::take(&mut self.lifetimes_to_define); + (lifetimes_to_define, res) } /// Converts a lifetime into a new generic parameter. @@ -785,27 +772,39 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { anonymous_lifetime_mode: AnonymousLifetimeMode, f: impl FnOnce(&mut Self, &mut Vec>) -> T, ) -> (hir::Generics<'hir>, T) { - let (in_band_defs, (mut lowered_generics, res)) = - self.with_in_scope_lifetime_defs(&generics.params, |this| { - this.collect_in_band_defs(parent_def_id, anonymous_lifetime_mode, |this| { - let mut params = Vec::new(); - // Note: it is necessary to lower generics *before* calling `f`. - // When lowering `async fn`, there's a final step when lowering - // the return type that assumes that all in-scope lifetimes have - // already been added to either `in_scope_lifetimes` or - // `lifetimes_to_define`. If we swapped the order of these two, - // in-band-lifetimes introduced by generics or where-clauses - // wouldn't have been added yet. - let generics = this.lower_generics_mut( - generics, - ImplTraitContext::Universal(&mut params, this.current_hir_id_owner), - ); - let res = f(this, &mut params); - (params, (generics, res)) + let (lifetimes_to_define, (mut lowered_generics, impl_trait_defs, res)) = self + .collect_in_band_defs(|this| { + this.with_anonymous_lifetime_mode(anonymous_lifetime_mode, |this| { + this.with_in_scope_lifetime_defs(&generics.params, |this| { + let mut impl_trait_defs = Vec::new(); + // Note: it is necessary to lower generics *before* calling `f`. + // When lowering `async fn`, there's a final step when lowering + // the return type that assumes that all in-scope lifetimes have + // already been added to either `in_scope_lifetimes` or + // `lifetimes_to_define`. If we swapped the order of these two, + // in-band-lifetimes introduced by generics or where-clauses + // wouldn't have been added yet. + let generics = this.lower_generics_mut( + generics, + ImplTraitContext::Universal( + &mut impl_trait_defs, + this.current_hir_id_owner, + ), + ); + let res = f(this, &mut impl_trait_defs); + (generics, impl_trait_defs, res) + }) }) }); - lowered_generics.params.extend(in_band_defs); + lowered_generics.params.extend( + lifetimes_to_define + .into_iter() + .map(|(span, hir_name)| { + self.lifetime_to_generic_param(span, hir_name, parent_def_id) + }) + .chain(impl_trait_defs), + ); let lowered_generics = lowered_generics.into_generics(self.arena); (lowered_generics, res) From 72b6f7049c0903ac266dc67510b655441528bdf2 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 29 Nov 2021 22:59:13 +0100 Subject: [PATCH 17/20] Use collect_in_band_defs for async lifetime captures. --- compiler/rustc_ast_lowering/src/lib.rs | 98 +++++++++---------- .../ui/async-await/generics-and-bounds.rs | 11 +++ 2 files changed, 55 insertions(+), 54 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index ec5022679d439..667e94656f600 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -648,15 +648,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &mut self, f: impl FnOnce(&mut Self) -> T, ) -> (Vec<(Span, ParamName)>, T) { - assert!(!self.is_collecting_in_band_lifetimes); - assert!(self.lifetimes_to_define.is_empty()); - self.is_collecting_in_band_lifetimes = true; + let was_collecting = std::mem::replace(&mut self.is_collecting_in_band_lifetimes, true); + let len = self.lifetimes_to_define.len(); let res = f(self); - self.is_collecting_in_band_lifetimes = false; - - let lifetimes_to_define = std::mem::take(&mut self.lifetimes_to_define); + let lifetimes_to_define = self.lifetimes_to_define.split_off(len); + self.is_collecting_in_band_lifetimes = was_collecting; (lifetimes_to_define, res) } @@ -1688,18 +1686,29 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // this is because the elided lifetimes from the return type // should be figured out using the ordinary elision rules, and // this desugaring achieves that. + + debug!("lower_async_fn_ret_ty: in_scope_lifetimes={:#?}", self.in_scope_lifetimes); + debug!("lower_async_fn_ret_ty: lifetimes_to_define={:#?}", self.lifetimes_to_define); + + // Calculate all the lifetimes that should be captured + // by the opaque type. This should include all in-scope + // lifetime parameters, including those defined in-band. // - // The variable `input_lifetimes_count` tracks the number of - // lifetime parameters to the opaque type *not counting* those - // lifetimes elided in the return type. This includes those - // that are explicitly declared (`in_scope_lifetimes`) and - // those elided lifetimes we found in the arguments (current - // content of `lifetimes_to_define`). Next, we will process - // the return type, which will cause `lifetimes_to_define` to - // grow. - let input_lifetimes_count = self.in_scope_lifetimes.len() + self.lifetimes_to_define.len(); - - let mut lifetime_params = Vec::new(); + // `lifetime_params` is a vector of tuple (span, parameter name, lifetime name). + + // Input lifetime like `'a` or `'1`: + let mut lifetime_params: Vec<_> = self + .in_scope_lifetimes + .iter() + .cloned() + .map(|name| (name.ident().span, name, hir::LifetimeName::Param(name))) + .chain( + self.lifetimes_to_define + .iter() + .map(|&(span, name)| (span, name, hir::LifetimeName::Param(name))), + ) + .collect(); + self.with_hir_id_owner(opaque_ty_node_id, |this| { // We have to be careful to get elision right here. The // idea is that we create a lifetime parameter for each @@ -1709,34 +1718,26 @@ 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 - .with_anonymous_lifetime_mode(AnonymousLifetimeMode::CreateParameter, |this| { - this.lower_async_fn_output_type_to_future_bound(output, fn_def_id, span) + let (lifetimes_to_define, future_bound) = + this.with_anonymous_lifetime_mode(AnonymousLifetimeMode::CreateParameter, |this| { + this.collect_in_band_defs(|this| { + this.lower_async_fn_output_type_to_future_bound(output, fn_def_id, span) + }) }); - debug!("lower_async_fn_ret_ty: future_bound={:#?}", future_bound); + debug!("lower_async_fn_ret_ty: lifetimes_to_define={:#?}", lifetimes_to_define); - // Calculate all the lifetimes that should be captured - // by the opaque type. This should include all in-scope - // lifetime parameters, including those defined in-band. - // - // Note: this must be done after lowering the output type, - // as the output type may introduce new in-band lifetimes. - lifetime_params = this - .in_scope_lifetimes - .iter() - .cloned() - .map(|name| (name.ident().span, name)) - .chain(this.lifetimes_to_define.iter().cloned()) - .collect(); - - debug!("lower_async_fn_ret_ty: in_scope_lifetimes={:#?}", this.in_scope_lifetimes); - debug!("lower_async_fn_ret_ty: lifetimes_to_define={:#?}", this.lifetimes_to_define); + lifetime_params.extend( + // Output lifetime like `'_`: + lifetimes_to_define + .into_iter() + .map(|(span, name)| (span, name, hir::LifetimeName::Implicit(false))), + ); debug!("lower_async_fn_ret_ty: lifetime_params={:#?}", lifetime_params); let generic_params = - this.arena.alloc_from_iter(lifetime_params.iter().map(|(span, hir_name)| { - this.lifetime_to_generic_param(*span, *hir_name, opaque_ty_def_id) + this.arena.alloc_from_iter(lifetime_params.iter().map(|&(span, hir_name, _)| { + this.lifetime_to_generic_param(span, hir_name, opaque_ty_def_id) })); let opaque_ty_item = hir::OpaqueTy { @@ -1770,25 +1771,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // // For the "output" lifetime parameters, we just want to // generate `'_`. - let mut generic_args = Vec::with_capacity(lifetime_params.len()); - generic_args.extend(lifetime_params[..input_lifetimes_count].iter().map( - |&(span, hir_name)| { - // Input lifetime like `'a` or `'1`: + let generic_args = + self.arena.alloc_from_iter(lifetime_params.into_iter().map(|(span, _, name)| { GenericArg::Lifetime(hir::Lifetime { hir_id: self.next_id(), span: self.lower_span(span), - name: hir::LifetimeName::Param(hir_name), + name, }) - }, - )); - generic_args.extend(lifetime_params[input_lifetimes_count..].iter().map(|&(span, _)| - // Output lifetime like `'_`. - GenericArg::Lifetime(hir::Lifetime { - hir_id: self.next_id(), - span: self.lower_span(span), - name: hir::LifetimeName::Implicit(false), - }))); - let generic_args = self.arena.alloc_from_iter(generic_args); + })); // Create the `Foo<...>` reference itself. Note that the `type // Foo = impl Trait` is, internally, created as a child of the diff --git a/src/test/ui/async-await/generics-and-bounds.rs b/src/test/ui/async-await/generics-and-bounds.rs index 963b19b34a620..90ab0c01f5450 100644 --- a/src/test/ui/async-await/generics-and-bounds.rs +++ b/src/test/ui/async-await/generics-and-bounds.rs @@ -2,6 +2,8 @@ // edition:2018 // compile-flags: --crate-type lib +#![feature(in_band_lifetimes)] + use std::future::Future; pub async fn simple_generic() {} @@ -71,6 +73,10 @@ pub fn call_with_ref_block<'a>(f: &'a (impl Foo + 'a)) -> impl Future impl Future + 'a { + async move { f.foo() } +} + pub fn async_block_with_same_generic_params_unifies() { let mut a = call_generic_bound_block(FooType); a = call_generic_bound_block(FooType); @@ -85,4 +91,9 @@ pub fn async_block_with_same_generic_params_unifies() { let f_two = FooType; let mut d = call_with_ref_block(&f_one); d = call_with_ref_block(&f_two); + + let f_one = FooType; + let f_two = FooType; + let mut d = call_with_ref_block_in_band(&f_one); + d = call_with_ref_block_in_band(&f_two); } From 8576ab45e4fc192524ab615f3309d9b552528828 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 30 Nov 2021 19:11:35 +0100 Subject: [PATCH 18/20] Store impl_trait_fn inside OpaqueTyOrigin. --- compiler/rustc_ast_lowering/src/item.rs | 9 +-- compiler/rustc_ast_lowering/src/lib.rs | 25 +++--- .../src/region_infer/opaque_types.rs | 2 +- compiler/rustc_hir/src/hir.rs | 9 ++- .../error_reporting/nice_region_error/util.rs | 2 +- .../rustc_infer/src/infer/opaque_types.rs | 22 +++--- compiler/rustc_middle/src/ty/mod.rs | 18 +++-- compiler/rustc_resolve/src/late/lifetimes.rs | 15 +++- compiler/rustc_ty_utils/src/ty.rs | 4 +- compiler/rustc_typeck/src/astconv/mod.rs | 13 ++- compiler/rustc_typeck/src/check/check.rs | 8 +- compiler/rustc_typeck/src/collect.rs | 79 +++++++++++-------- compiler/rustc_typeck/src/collect/type_of.rs | 8 +- 13 files changed, 118 insertions(+), 96 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 692f39368243a..ca7a64e254e14 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -247,12 +247,7 @@ impl<'hir> LoweringContext<'_, 'hir> { AnonymousLifetimeMode::PassThrough, |this, idty| { let ret_id = asyncness.opt_return_id(); - this.lower_fn_decl( - &decl, - Some((fn_def_id.to_def_id(), idty)), - true, - ret_id, - ) + this.lower_fn_decl(&decl, Some((fn_def_id, idty)), true, ret_id) }, ); let sig = hir::FnSig { @@ -1264,7 +1259,7 @@ impl<'hir> LoweringContext<'_, 'hir> { |this, idty| { this.lower_fn_decl( &sig.decl, - Some((fn_def_id.to_def_id(), idty)), + Some((fn_def_id, idty)), impl_trait_return_allow, is_async, ) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 667e94656f600..c04b0471cb72f 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -228,7 +228,7 @@ enum ImplTraitContext<'b, 'a> { ReturnPositionOpaqueTy { /// `DefId` for the parent function, used to look up necessary /// information later. - fn_def_id: DefId, + fn_def_id: LocalDefId, /// Origin: Either OpaqueTyOrigin::FnReturn or OpaqueTyOrigin::AsyncFn, origin: hir::OpaqueTyOrigin, }, @@ -1377,7 +1377,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_opaque_impl_trait( &mut self, span: Span, - fn_def_id: Option, + fn_def_id: Option, origin: hir::OpaqueTyOrigin, opaque_ty_node_id: NodeId, capturable_lifetimes: Option<&FxHashSet>, @@ -1449,7 +1449,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span: lctx.lower_span(span), }, bounds: hir_bounds, - impl_trait_fn: fn_def_id, origin, }; @@ -1519,7 +1518,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_fn_decl( &mut self, decl: &FnDecl, - mut in_band_ty_params: Option<(DefId, &mut Vec>)>, + mut in_band_ty_params: Option<(LocalDefId, &mut Vec>)>, impl_trait_return_allow: bool, make_ret_async: Option, ) -> &'hir hir::FnDecl<'hir> { @@ -1577,7 +1576,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { Some((def_id, _)) if impl_trait_return_allow => { ImplTraitContext::ReturnPositionOpaqueTy { fn_def_id: def_id, - origin: hir::OpaqueTyOrigin::FnReturn, + origin: hir::OpaqueTyOrigin::FnReturn(def_id), } } _ => ImplTraitContext::disallowed(), @@ -1632,7 +1631,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_async_fn_ret_ty( &mut self, output: &FnRetTy, - fn_def_id: DefId, + fn_def_id: LocalDefId, opaque_ty_node_id: NodeId, ) -> hir::FnRetTy<'hir> { debug!( @@ -1747,8 +1746,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span: this.lower_span(span), }, bounds: arena_vec![this; future_bound], - impl_trait_fn: Some(fn_def_id), - origin: hir::OpaqueTyOrigin::AsyncFn, + origin: hir::OpaqueTyOrigin::AsyncFn(fn_def_id), }; trace!("exist ty from async fn def id: {:#?}", opaque_ty_def_id); @@ -1794,7 +1792,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_async_fn_output_type_to_future_bound( &mut self, output: &FnRetTy, - fn_def_id: DefId, + fn_def_id: LocalDefId, span: Span, ) -> hir::GenericBound<'hir> { // Compute the `T` in `Future` from the return type. @@ -1805,7 +1803,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // generates. let context = ImplTraitContext::ReturnPositionOpaqueTy { fn_def_id, - origin: hir::OpaqueTyOrigin::FnReturn, + origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), }; self.lower_ty(ty, context) } @@ -2442,17 +2440,12 @@ impl<'hir> GenericArgsCtor<'hir> { } } +#[tracing::instrument(level = "debug")] fn lifetimes_from_impl_trait_bounds( opaque_ty_id: NodeId, bounds: hir::GenericBounds<'_>, lifetimes_to_include: Option<&FxHashSet>, ) -> Vec<(hir::LifetimeName, Span)> { - debug!( - "lifetimes_from_impl_trait_bounds(opaque_ty_id={:?}, \ - bounds={:#?})", - opaque_ty_id, bounds, - ); - // This visitor walks over `impl Trait` bounds and creates defs for all lifetimes that // appear in the bounds, excluding lifetimes that are created within the bounds. // E.g., `'a`, `'b`, but not `'c` in `impl for<'c> SomeTrait<'a, 'b, 'c>`. diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index 4eb7be542e7a1..76b3be7976c61 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -173,7 +173,7 @@ fn check_opaque_type_parameter_valid( // fn foo() -> foo::<'static..'static>::Foo<'l0..'lm>. // // which would error here on all of the `'static` args. - OpaqueTyOrigin::FnReturn | OpaqueTyOrigin::AsyncFn => return true, + OpaqueTyOrigin::FnReturn(..) | OpaqueTyOrigin::AsyncFn(..) => return true, // Check these OpaqueTyOrigin::TyAlias => {} } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 487ae87052ba3..d393ea6893849 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2248,7 +2248,6 @@ pub struct BareFnTy<'hir> { pub struct OpaqueTy<'hir> { pub generics: Generics<'hir>, pub bounds: GenericBounds<'hir>, - pub impl_trait_fn: Option, pub origin: OpaqueTyOrigin, } @@ -2256,9 +2255,9 @@ pub struct OpaqueTy<'hir> { #[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, HashStable_Generic)] pub enum OpaqueTyOrigin { /// `-> impl Trait` - FnReturn, + FnReturn(LocalDefId), /// `async fn` - AsyncFn, + AsyncFn(LocalDefId), /// type aliases: `type Foo = impl Trait;` TyAlias, } @@ -2809,7 +2808,9 @@ impl ItemKind<'_> { Some(match *self { ItemKind::Fn(_, ref generics, _) | ItemKind::TyAlias(_, ref generics) - | ItemKind::OpaqueTy(OpaqueTy { ref generics, impl_trait_fn: None, .. }) + | ItemKind::OpaqueTy(OpaqueTy { + ref generics, origin: OpaqueTyOrigin::TyAlias, .. + }) | ItemKind::Enum(_, ref generics) | ItemKind::Struct(_, ref generics) | ItemKind::Union(_, ref generics) diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs index 90bc5b3b2fed1..04eceecc5f072 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs @@ -107,7 +107,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, - origin: hir::OpaqueTyOrigin::AsyncFn, + origin: hir::OpaqueTyOrigin::AsyncFn(..), .. }), .. diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index d9ab4ae1eda29..754d5a6ed7251 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -276,7 +276,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { debug!(?concrete_ty); let first_own_region = match opaque_defn.origin { - hir::OpaqueTyOrigin::FnReturn | hir::OpaqueTyOrigin::AsyncFn => { + hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => { // We lower // // fn foo<'l0..'ln>() -> impl Trait<'l0..'lm> @@ -463,20 +463,24 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { let parent_def_id = self.infcx.defining_use_anchor; let (in_definition_scope, origin) = match tcx.hir().expect_item(def_id).kind { + // Async `impl Trait` + hir::ItemKind::OpaqueTy(hir::OpaqueTy { + origin: hir::OpaqueTyOrigin::AsyncFn(parent), + .. + }) => (parent == parent_def_id, hir::OpaqueTyOrigin::AsyncFn(parent)), // Anonymous `impl Trait` hir::ItemKind::OpaqueTy(hir::OpaqueTy { - impl_trait_fn: Some(parent), - origin, + origin: hir::OpaqueTyOrigin::FnReturn(parent), .. - }) => (parent == parent_def_id.to_def_id(), origin), + }) => (parent == parent_def_id, hir::OpaqueTyOrigin::FnReturn(parent)), // Named `type Foo = impl Bar;` hir::ItemKind::OpaqueTy(hir::OpaqueTy { - impl_trait_fn: None, - origin, + origin: hir::OpaqueTyOrigin::TyAlias, .. - }) => { - (may_define_opaque_type(tcx, parent_def_id, opaque_hir_id), origin) - } + }) => ( + may_define_opaque_type(tcx, parent_def_id, opaque_hir_id), + hir::OpaqueTyOrigin::TyAlias, + ), ref itemkind => { span_bug!( self.value_span, diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 7e1804673df2c..fd1409949f0a7 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2055,13 +2055,17 @@ impl<'tcx> TyCtxt<'tcx> { } } -/// Yields the parent function's `DefId` if `def_id` is an `impl Trait` definition. -pub fn is_impl_trait_defn(tcx: TyCtxt<'_>, def_id: DefId) -> Option { - if let Some(def_id) = def_id.as_local() { - if let Node::Item(item) = tcx.hir().get(tcx.hir().local_def_id_to_hir_id(def_id)) { - if let hir::ItemKind::OpaqueTy(ref opaque_ty) = item.kind { - return opaque_ty.impl_trait_fn; - } +/// Yields the parent function's `LocalDefId` if `def_id` is an `impl Trait` definition. +pub fn is_impl_trait_defn(tcx: TyCtxt<'_>, def_id: DefId) -> Option { + let def_id = def_id.as_local()?; + if let Node::Item(item) = tcx.hir().get(tcx.hir().local_def_id_to_hir_id(def_id)) { + if let hir::ItemKind::OpaqueTy(ref opaque_ty) = item.kind { + return match opaque_ty.origin { + hir::OpaqueTyOrigin::FnReturn(parent) | hir::OpaqueTyOrigin::AsyncFn(parent) => { + Some(parent) + } + hir::OpaqueTyOrigin::TyAlias => None, + }; } } None diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index 1ff33689b53c7..c94c56df75b78 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -968,7 +968,10 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { let (generics, bounds) = match opaque_ty.kind { // Named opaque `impl Trait` types are reached via `TyKind::Path`. // This arm is for `impl Trait` in the types of statics, constants and locals. - hir::ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn: None, .. }) => { + hir::ItemKind::OpaqueTy(hir::OpaqueTy { + origin: hir::OpaqueTyOrigin::TyAlias, + .. + }) => { intravisit::walk_ty(self, ty); // Elided lifetimes are not allowed in non-return @@ -985,7 +988,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } // RPIT (return position impl trait) hir::ItemKind::OpaqueTy(hir::OpaqueTy { - impl_trait_fn: Some(_), + origin: hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..), ref generics, bounds, .. @@ -1695,7 +1698,11 @@ fn compute_object_lifetime_defaults( hir::ItemKind::Struct(_, ref generics) | hir::ItemKind::Union(_, ref generics) | hir::ItemKind::Enum(_, ref generics) - | hir::ItemKind::OpaqueTy(hir::OpaqueTy { ref generics, impl_trait_fn: None, .. }) + | hir::ItemKind::OpaqueTy(hir::OpaqueTy { + ref generics, + origin: hir::OpaqueTyOrigin::TyAlias, + .. + }) | hir::ItemKind::TyAlias(_, ref generics) | hir::ItemKind::Trait(_, _, ref generics, ..) => { let result = object_lifetime_defaults_for_item(tcx, generics); @@ -2067,7 +2074,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { .. }) = self.tcx.hir().get(parent_hir_id) { - if opaque.origin != hir::OpaqueTyOrigin::AsyncFn { + if !matches!(opaque.origin, hir::OpaqueTyOrigin::AsyncFn(..)) { continue 'lifetimes; } // We want to do this only if the liftime identifier is already defined diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 711a6f2fbebdd..74a015d4c348e 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -248,7 +248,7 @@ fn trait_of_item(tcx: TyCtxt<'_>, def_id: DefId) -> Option { fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> { // The param_env of an impl Trait type is its defining function's param_env if let Some(parent) = ty::is_impl_trait_defn(tcx, def_id) { - return param_env(tcx, parent); + return param_env(tcx, parent.to_def_id()); } // Compute the bounds on Self and the type parameters. @@ -313,7 +313,7 @@ fn well_formed_types_in_env<'tcx>( // The environment of an impl Trait type is its defining function's environment. if let Some(parent) = ty::is_impl_trait_defn(tcx, def_id) { - return well_formed_types_in_env(tcx, parent); + return well_formed_types_in_env(tcx, parent.to_def_id()); } // Compute the bounds on `Self` and the type parameters. diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 08261fedd4a25..908adeb22b364 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -2336,9 +2336,16 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let def_id = item_id.def_id.to_def_id(); match opaque_ty.kind { - hir::ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn, .. }) => { - self.impl_trait_ty_to_ty(def_id, lifetimes, impl_trait_fn.is_some()) - } + hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => self + .impl_trait_ty_to_ty( + def_id, + lifetimes, + matches!( + origin, + hir::OpaqueTyOrigin::FnReturn(..) + | hir::OpaqueTyOrigin::AsyncFn(..) + ), + ), ref i => bug!("`impl Trait` pointed to non-opaque type?? {:#?}", i), } } diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 2061f955d968f..a6b16e7f0d4d8 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -541,7 +541,7 @@ pub(super) fn check_opaque_for_inheriting_lifetimes( } if let ItemKind::OpaqueTy(hir::OpaqueTy { - origin: hir::OpaqueTyOrigin::AsyncFn | hir::OpaqueTyOrigin::FnReturn, + origin: hir::OpaqueTyOrigin::AsyncFn(..) | hir::OpaqueTyOrigin::FnReturn(..), .. }) = item.kind { @@ -567,7 +567,7 @@ pub(super) fn check_opaque_for_inheriting_lifetimes( visitor.visit_item(&item); let is_async = match item.kind { ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => { - matches!(origin, hir::OpaqueTyOrigin::AsyncFn) + matches!(origin, hir::OpaqueTyOrigin::AsyncFn(..)) } _ => unreachable!(), }; @@ -604,7 +604,7 @@ pub(super) fn check_opaque_for_cycles<'tcx>( ) -> Result<(), ErrorReported> { if tcx.try_expand_impl_trait_type(def_id.to_def_id(), substs).is_err() { match origin { - hir::OpaqueTyOrigin::AsyncFn => async_opaque_type_cycle_error(tcx, span), + hir::OpaqueTyOrigin::AsyncFn(..) => async_opaque_type_cycle_error(tcx, span), _ => opaque_type_cycle_error(tcx, def_id, span), } Err(ErrorReported) @@ -635,7 +635,7 @@ fn check_opaque_meets_bounds<'tcx>( ) { match origin { // Checked when type checking the function containing them. - hir::OpaqueTyOrigin::FnReturn | hir::OpaqueTyOrigin::AsyncFn => return, + hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => return, // Can have different predicates to their defining use hir::OpaqueTyOrigin::TyAlias => {} } diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 67a3053c60786..e8d28dd75d6aa 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -594,7 +594,11 @@ fn type_param_predicates( ItemKind::Fn(.., ref generics, _) | ItemKind::Impl(hir::Impl { ref generics, .. }) | ItemKind::TyAlias(_, ref generics) - | ItemKind::OpaqueTy(OpaqueTy { ref generics, impl_trait_fn: None, .. }) + | ItemKind::OpaqueTy(OpaqueTy { + ref generics, + origin: hir::OpaqueTyOrigin::TyAlias, + .. + }) | ItemKind::Enum(_, ref generics) | ItemKind::Struct(_, ref generics) | ItemKind::Union(_, ref generics) => generics, @@ -793,7 +797,10 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { } // Desugared from `impl Trait`, so visited by the function's return type. - hir::ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn: Some(_), .. }) => {} + hir::ItemKind::OpaqueTy(hir::OpaqueTy { + origin: hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..), + .. + }) => {} // Don't call `type_of` on opaque types, since that depends on type // checking function bodies. `check_item_type` ensures that it's called @@ -1488,15 +1495,18 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { Some(tcx.typeck_root_def_id(def_id)) } Node::Item(item) => match item.kind { - ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn, .. }) => { - impl_trait_fn.or_else(|| { - let parent_id = tcx.hir().get_parent_item(hir_id); - assert!(parent_id != hir_id && parent_id != CRATE_HIR_ID); - debug!("generics_of: parent of opaque ty {:?} is {:?}", def_id, parent_id); - // Opaque types are always nested within another item, and - // inherit the generics of the item. - Some(tcx.hir().local_def_id(parent_id).to_def_id()) - }) + ItemKind::OpaqueTy(hir::OpaqueTy { + origin: + hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id), + .. + }) => Some(fn_def_id.to_def_id()), + ItemKind::OpaqueTy(hir::OpaqueTy { origin: hir::OpaqueTyOrigin::TyAlias, .. }) => { + let parent_id = tcx.hir().get_parent_item(hir_id); + assert!(parent_id != hir_id && parent_id != CRATE_HIR_ID); + debug!("generics_of: parent of opaque ty {:?} is {:?}", def_id, parent_id); + // Opaque types are always nested within another item, and + // inherit the generics of the item. + Some(tcx.hir().local_def_id(parent_id).to_def_id()) } _ => None, }, @@ -2051,31 +2061,32 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP generics } ItemKind::OpaqueTy(OpaqueTy { - bounds: _, - impl_trait_fn, + origin: hir::OpaqueTyOrigin::AsyncFn(..) | hir::OpaqueTyOrigin::FnReturn(..), + .. + }) => { + // return-position impl trait + // + // We don't inherit predicates from the parent here: + // If we have, say `fn f<'a, T: 'a>() -> impl Sized {}` + // then the return type is `f::<'static, T>::{{opaque}}`. + // + // If we inherited the predicates of `f` then we would + // require that `T: 'static` to show that the return + // type is well-formed. + // + // The only way to have something with this opaque type + // is from the return type of the containing function, + // which will ensure that the function's predicates + // hold. + return ty::GenericPredicates { parent: None, predicates: &[] }; + } + ItemKind::OpaqueTy(OpaqueTy { ref generics, - origin: _, + origin: hir::OpaqueTyOrigin::TyAlias, + .. }) => { - if impl_trait_fn.is_some() { - // return-position impl trait - // - // We don't inherit predicates from the parent here: - // If we have, say `fn f<'a, T: 'a>() -> impl Sized {}` - // then the return type is `f::<'static, T>::{{opaque}}`. - // - // If we inherited the predicates of `f` then we would - // require that `T: 'static` to show that the return - // type is well-formed. - // - // The only way to have something with this opaque type - // is from the return type of the containing function, - // which will ensure that the function's predicates - // hold. - return ty::GenericPredicates { parent: None, predicates: &[] }; - } else { - // type-alias impl trait - generics - } + // type-alias impl trait + generics } _ => NO_GENERICS, diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index b684844744de3..af199ca99460f 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -394,13 +394,13 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id()); tcx.mk_adt(def, substs) } - ItemKind::OpaqueTy(OpaqueTy { impl_trait_fn: None, .. }) => { + ItemKind::OpaqueTy(OpaqueTy { origin: hir::OpaqueTyOrigin::TyAlias, .. }) => { find_opaque_ty_constraints(tcx, def_id) } // Opaque types desugared from `impl Trait`. - ItemKind::OpaqueTy(OpaqueTy { impl_trait_fn: Some(owner), .. }) => { + ItemKind::OpaqueTy(OpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn(owner) | hir::OpaqueTyOrigin::AsyncFn(owner), .. }) => { let concrete_ty = tcx - .mir_borrowck(owner.expect_local()) + .mir_borrowck(owner) .concrete_opaque_types .get_value_matching(|(key, _)| key.def_id == def_id.to_def_id()) .copied() @@ -413,7 +413,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { ), ); if let Some(ErrorReported) = - tcx.typeck(owner.expect_local()).tainted_by_errors + tcx.typeck(owner).tainted_by_errors { // Some error in the // owner fn prevented us from populating From 54ff72132c860726f40e0ff6d547b039de0a1323 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 7 Dec 2021 22:49:07 +0100 Subject: [PATCH 19/20] Simplify match. --- .../rustc_infer/src/infer/opaque_types.rs | 40 +++++++------------ 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 754d5a6ed7251..c2ef0b41e27bf 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -461,39 +461,29 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { if let Some(def_id) = def_id.as_local() { let opaque_hir_id = tcx.hir().local_def_id_to_hir_id(def_id); let parent_def_id = self.infcx.defining_use_anchor; - let (in_definition_scope, origin) = match tcx.hir().expect_item(def_id).kind - { + let item_kind = &tcx.hir().expect_item(def_id).kind; + let hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) = item_kind else { + span_bug!( + self.value_span, + "weird opaque type: {:#?}, {:#?}", + ty.kind(), + item_kind + ) + }; + let in_definition_scope = match *origin { // Async `impl Trait` - hir::ItemKind::OpaqueTy(hir::OpaqueTy { - origin: hir::OpaqueTyOrigin::AsyncFn(parent), - .. - }) => (parent == parent_def_id, hir::OpaqueTyOrigin::AsyncFn(parent)), + hir::OpaqueTyOrigin::AsyncFn(parent) => parent == parent_def_id, // Anonymous `impl Trait` - hir::ItemKind::OpaqueTy(hir::OpaqueTy { - origin: hir::OpaqueTyOrigin::FnReturn(parent), - .. - }) => (parent == parent_def_id, hir::OpaqueTyOrigin::FnReturn(parent)), + hir::OpaqueTyOrigin::FnReturn(parent) => parent == parent_def_id, // Named `type Foo = impl Bar;` - hir::ItemKind::OpaqueTy(hir::OpaqueTy { - origin: hir::OpaqueTyOrigin::TyAlias, - .. - }) => ( - may_define_opaque_type(tcx, parent_def_id, opaque_hir_id), - hir::OpaqueTyOrigin::TyAlias, - ), - ref itemkind => { - span_bug!( - self.value_span, - "weird opaque type: {:#?}, {:#?}", - ty.kind(), - itemkind - ) + hir::OpaqueTyOrigin::TyAlias => { + may_define_opaque_type(tcx, parent_def_id, opaque_hir_id) } }; if in_definition_scope { let opaque_type_key = OpaqueTypeKey { def_id: def_id.to_def_id(), substs }; - return self.fold_opaque_ty(ty, opaque_type_key, origin); + return self.fold_opaque_ty(ty, opaque_type_key, *origin); } debug!( From 908f300dd7878f6bcd0f5479c2db680067aec3d8 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Thu, 11 Nov 2021 12:42:38 +0000 Subject: [PATCH 20/20] Remove the reg_thumb register class for asm! on ARM Also restricts r8-r14 from being used on Thumb1 targets as per #90736. --- compiler/rustc_codegen_gcc/src/asm.rs | 7 +--- compiler/rustc_codegen_llvm/src/asm.rs | 7 +--- .../rustc_codegen_ssa/src/target_features.rs | 1 + compiler/rustc_span/src/symbol.rs | 1 - compiler/rustc_target/src/asm/arm.rs | 37 ++++++++++++------- .../unstable-book/src/library-features/asm.md | 6 +-- src/test/assembly/asm/arm-modifiers.rs | 6 --- src/test/assembly/asm/arm-types.rs | 30 --------------- 8 files changed, 30 insertions(+), 65 deletions(-) diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs index 7481b5db755e7..10edcf36955da 100644 --- a/compiler/rustc_codegen_gcc/src/asm.rs +++ b/compiler/rustc_codegen_gcc/src/asm.rs @@ -568,7 +568,6 @@ fn reg_to_gcc(reg: InlineAsmRegOrRegClass) -> ConstraintOrRegister { InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg) => unimplemented!(), InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => unimplemented!(), InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) => unimplemented!(), - InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg_thumb) => unimplemented!(), InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg) | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg_low16) | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low8) => unimplemented!(), @@ -628,8 +627,7 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl | InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => { unimplemented!() } - InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) - | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg_thumb) => cx.type_i32(), + InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg)=> cx.type_i32(), InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg) | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg_low16) => cx.type_f32(), InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg) @@ -737,8 +735,7 @@ fn modifier_to_gcc(arch: InlineAsmArch, reg: InlineAsmRegClass, modifier: Option | InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => { unimplemented!() } - InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) - | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg_thumb) => unimplemented!(), + InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) => unimplemented!(), InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg) | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg_low16) => unimplemented!(), InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg) diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index 90d3c0fb2f173..f3c3a17490811 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -632,7 +632,6 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'tcx>>) unreachable!("clobber-only") } InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) => "r", - InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg_thumb) => "l", InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg) | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg_low16) | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low8) => "t", @@ -703,8 +702,7 @@ fn modifier_to_llvm( InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => { unreachable!("clobber-only") } - InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) - | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg_thumb) => None, + InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) => None, InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg) | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg_low16) => None, InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg) @@ -785,8 +783,7 @@ fn dummy_output_type(cx: &CodegenCx<'ll, 'tcx>, reg: InlineAsmRegClass) -> &'ll InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => { unreachable!("clobber-only") } - InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) - | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg_thumb) => cx.type_i32(), + InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) => cx.type_i32(), InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg) | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg_low16) => cx.type_f32(), InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg) diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index b4420df5df417..ba72e3cfafce2 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -35,6 +35,7 @@ const ARM_ALLOWED_FEATURES: &[(&str, Option)] = &[ // since it should be enabled per-function using #[instruction_set], not // #[target_feature]. ("thumb-mode", Some(sym::arm_target_feature)), + ("thumb2", Some(sym::arm_target_feature)), ]; const AARCH64_ALLOWED_FEATURES: &[(&str, Option)] = &[ diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index a4280047c7068..2a7af9cf67ae3 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1057,7 +1057,6 @@ symbols! { reg_nonzero, reg_pair, reg_ptr, - reg_thumb, reg_upper, register_attr, register_tool, diff --git a/compiler/rustc_target/src/asm/arm.rs b/compiler/rustc_target/src/asm/arm.rs index 4c323fc35d643..4eeb7fcc71bce 100644 --- a/compiler/rustc_target/src/asm/arm.rs +++ b/compiler/rustc_target/src/asm/arm.rs @@ -6,7 +6,6 @@ use std::fmt; def_reg_class! { Arm ArmInlineAsmRegClass { reg, - reg_thumb, sreg, sreg_low16, dreg, @@ -47,7 +46,7 @@ impl ArmInlineAsmRegClass { _arch: InlineAsmArch, ) -> &'static [(InlineAsmType, Option<&'static str>)] { match self { - Self::reg | Self::reg_thumb => types! { _: I8, I16, I32, F32; }, + Self::reg => types! { _: I8, I16, I32, F32; }, Self::sreg | Self::sreg_low16 => types! { "vfp2": I32, F32; }, Self::dreg | Self::dreg_low16 | Self::dreg_low8 => types! { "vfp2": I64, F64, VecI8(8), VecI16(4), VecI32(2), VecI64(1), VecF32(2); @@ -88,20 +87,32 @@ fn frame_pointer_r7( } } +fn not_thumb1( + _arch: InlineAsmArch, + mut has_feature: impl FnMut(&str) -> bool, + _target: &Target, +) -> Result<(), &'static str> { + if has_feature("thumb-mode") && !has_feature("thumb2") { + Err("high registers (r8+) cannot be used in Thumb-1 code") + } else { + Ok(()) + } +} + def_regs! { Arm ArmInlineAsmReg ArmInlineAsmRegClass { - r0: reg, reg_thumb = ["r0", "a1"], - r1: reg, reg_thumb = ["r1", "a2"], - r2: reg, reg_thumb = ["r2", "a3"], - r3: reg, reg_thumb = ["r3", "a4"], - r4: reg, reg_thumb = ["r4", "v1"], - r5: reg, reg_thumb = ["r5", "v2"], - r7: reg, reg_thumb = ["r7", "v4"] % frame_pointer_r7, - r8: reg = ["r8", "v5"], - r10: reg = ["r10", "sl"], + r0: reg = ["r0", "a1"], + r1: reg = ["r1", "a2"], + r2: reg = ["r2", "a3"], + r3: reg = ["r3", "a4"], + r4: reg = ["r4", "v1"], + r5: reg = ["r5", "v2"], + r7: reg = ["r7", "v4"] % frame_pointer_r7, + r8: reg = ["r8", "v5"] % not_thumb1, + r10: reg = ["r10", "sl"] % not_thumb1, r11: reg = ["r11", "fp"] % frame_pointer_r11, - r12: reg = ["r12", "ip"], - r14: reg = ["r14", "lr"], + r12: reg = ["r12", "ip"] % not_thumb1, + r14: reg = ["r14", "lr"] % not_thumb1, s0: sreg, sreg_low16 = ["s0"], s1: sreg, sreg_low16 = ["s1"], s2: sreg, sreg_low16 = ["s2"], diff --git a/src/doc/unstable-book/src/library-features/asm.md b/src/doc/unstable-book/src/library-features/asm.md index dffa3a8b80f0f..59987cccde673 100644 --- a/src/doc/unstable-book/src/library-features/asm.md +++ b/src/doc/unstable-book/src/library-features/asm.md @@ -564,12 +564,8 @@ Here is the list of currently supported register classes: | AArch64 | `vreg` | `v[0-31]` | `w` | | AArch64 | `vreg_low16` | `v[0-15]` | `x` | | AArch64 | `preg` | `p[0-15]`, `ffr` | Only clobbers | -| ARM (ARM) | `reg` | `r[0-12]`, `r14` | `r` | -| ARM (Thumb2) | `reg` | `r[0-12]`, `r14` | `r` | +| ARM (ARM/Thumb2) | `reg` | `r[0-12]`, `r14` | `r` | | ARM (Thumb1) | `reg` | `r[0-7]` | `r` | -| ARM (ARM) | `reg_thumb` | `r[0-r12]`, `r14` | `l` | -| ARM (Thumb2) | `reg_thumb` | `r[0-7]` | `l` | -| ARM (Thumb1) | `reg_thumb` | `r[0-7]` | `l` | | ARM | `sreg` | `s[0-31]` | `t` | | ARM | `sreg_low16` | `s[0-15]` | `x` | | ARM | `dreg` | `d[0-31]` | `w` | diff --git a/src/test/assembly/asm/arm-modifiers.rs b/src/test/assembly/asm/arm-modifiers.rs index a6985a3bf5c6b..88ffeaecfecb6 100644 --- a/src/test/assembly/asm/arm-modifiers.rs +++ b/src/test/assembly/asm/arm-modifiers.rs @@ -59,12 +59,6 @@ macro_rules! check { // CHECK: @NO_APP check!(reg "" reg i32 "mov"); -// CHECK-LABEL: reg_thumb: -// CHECK: @APP -// CHECK: mov r0, r0 -// CHECK: @NO_APP -check!(reg_thumb "" reg_thumb i32 "mov"); - // CHECK-LABEL: sreg: // CHECK: @APP // CHECK: vmov.f32 s0, s0 diff --git a/src/test/assembly/asm/arm-types.rs b/src/test/assembly/asm/arm-types.rs index 0c57b1fc4782d..5ac1af6afd67d 100644 --- a/src/test/assembly/asm/arm-types.rs +++ b/src/test/assembly/asm/arm-types.rs @@ -163,36 +163,6 @@ check!(reg_f32 f32 reg "mov"); // CHECK: @NO_APP check!(reg_ptr ptr reg "mov"); -// CHECK-LABEL: reg_thumb_i8: -// CHECK: @APP -// CHECK: mov {{[a-z0-9]+}}, {{[a-z0-9]+}} -// CHECK: @NO_APP -check!(reg_thumb_i8 i8 reg_thumb "mov"); - -// CHECK-LABEL: reg_thumb_i16: -// CHECK: @APP -// CHECK: mov {{[a-z0-9]+}}, {{[a-z0-9]+}} -// CHECK: @NO_APP -check!(reg_thumb_i16 i16 reg_thumb "mov"); - -// CHECK-LABEL: reg_thumb_i32: -// CHECK: @APP -// CHECK: mov {{[a-z0-9]+}}, {{[a-z0-9]+}} -// CHECK: @NO_APP -check!(reg_thumb_i32 i32 reg_thumb "mov"); - -// CHECK-LABEL: reg_thumb_f32: -// CHECK: @APP -// CHECK: mov {{[a-z0-9]+}}, {{[a-z0-9]+}} -// CHECK: @NO_APP -check!(reg_thumb_f32 f32 reg_thumb "mov"); - -// CHECK-LABEL: reg_thumb_ptr: -// CHECK: @APP -// CHECK: mov {{[a-z0-9]+}}, {{[a-z0-9]+}} -// CHECK: @NO_APP -check!(reg_thumb_ptr ptr reg_thumb "mov"); - // CHECK-LABEL: sreg_i32: // CHECK: @APP // CHECK: vmov.f32 s{{[0-9]+}}, s{{[0-9]+}}