diff options
Diffstat (limited to 'compiler')
15 files changed, 93 insertions, 24 deletions
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs index dce76fb1e77..4b1374ceef3 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs @@ -213,7 +213,9 @@ impl<'a> State<'a> { fn print_expr_call(&mut self, func: &ast::Expr, args: &[P<ast::Expr>], fixup: FixupContext) { let needs_paren = match func.kind { - ast::ExprKind::Field(..) => true, + // In order to call a named field, needs parens: `(self.fun)()` + // But not for an unnamed field: `self.0()` + ast::ExprKind::Field(_, name) => !name.is_numeric(), _ => func.precedence() < ExprPrecedence::Unambiguous, }; @@ -245,19 +247,21 @@ impl<'a> State<'a> { base_args: &[P<ast::Expr>], fixup: FixupContext, ) { - // Unlike in `print_expr_call`, no change to fixup here because + // The fixup here is different than in `print_expr_call` because // statement boundaries never occur in front of a `.` (or `?`) token. // - // match () { _ => f }.method(); + // Needs parens: + // + // (loop { break x; })(); + // + // Does not need parens: + // + // loop { break x; }.method(); // - // Parenthesizing only for precedence and not with regard to statement - // boundaries, `$receiver.method()` can be parsed back as a statement - // containing an expression if and only if `$receiver` can be parsed as - // a statement containing an expression. self.print_expr_cond_paren( receiver, receiver.precedence() < ExprPrecedence::Unambiguous, - fixup, + fixup.leftmost_subexpression_with_dot(), ); self.word("."); @@ -503,7 +507,7 @@ impl<'a> State<'a> { self.print_expr_cond_paren( expr, expr.precedence() < ExprPrecedence::Unambiguous, - fixup, + fixup.leftmost_subexpression_with_dot(), ); self.word_nbsp(".match"); } @@ -567,7 +571,7 @@ impl<'a> State<'a> { self.print_expr_cond_paren( expr, expr.precedence() < ExprPrecedence::Unambiguous, - fixup, + fixup.leftmost_subexpression_with_dot(), ); self.word(".await"); } @@ -606,7 +610,7 @@ impl<'a> State<'a> { self.print_expr_cond_paren( expr, expr.precedence() < ExprPrecedence::Unambiguous, - fixup, + fixup.leftmost_subexpression_with_dot(), ); self.word("."); self.print_ident(*ident); @@ -763,7 +767,11 @@ impl<'a> State<'a> { } } ast::ExprKind::Try(e) => { - self.print_expr_cond_paren(e, e.precedence() < ExprPrecedence::Unambiguous, fixup); + self.print_expr_cond_paren( + e, + e.precedence() < ExprPrecedence::Unambiguous, + fixup.leftmost_subexpression_with_dot(), + ); self.word("?") } ast::ExprKind::TryBlock(blk) => { diff --git a/compiler/rustc_ast_pretty/src/pprust/state/fixup.rs b/compiler/rustc_ast_pretty/src/pprust/state/fixup.rs index ff466703f73..3ef21f5cb29 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/fixup.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/fixup.rs @@ -138,6 +138,20 @@ impl FixupContext { } } + /// Transform this fixup into the one that should apply when printing a + /// leftmost subexpression followed by a `.` or `?` token, which confer + /// different statement boundary rules compared to other leftmost + /// subexpressions. + pub(crate) fn leftmost_subexpression_with_dot(self) -> Self { + FixupContext { + stmt: self.stmt || self.leftmost_subexpression_in_stmt, + leftmost_subexpression_in_stmt: false, + match_arm: self.match_arm || self.leftmost_subexpression_in_match_arm, + leftmost_subexpression_in_match_arm: false, + ..self + } + } + /// Transform this fixup into the one that should apply when printing any /// subexpression that is neither a leftmost subexpression nor surrounded in /// delimiters. diff --git a/compiler/rustc_borrowck/src/diagnostics/opaque_suggestions.rs b/compiler/rustc_borrowck/src/diagnostics/opaque_suggestions.rs index d77c53a3984..876b8f214b0 100644 --- a/compiler/rustc_borrowck/src/diagnostics/opaque_suggestions.rs +++ b/compiler/rustc_borrowck/src/diagnostics/opaque_suggestions.rs @@ -31,7 +31,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { diag: &mut Diag<'_>, ) { // We look at all the locals. Why locals? Because it's the best thing - // I could think of that's correlated with the *instantiated* higer-ranked + // I could think of that's correlated with the *instantiated* higher-ranked // binder for calls, since we don't really store those anywhere else. for ty in self.body.local_decls.iter().map(|local| local.ty) { if !ty.has_opaque_types() { diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index c29f3033dd0..f918f005a9b 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -140,6 +140,12 @@ pub(crate) fn type_check<'a, 'tcx>( &mut constraints, ); + let pre_obligations = infcx.take_registered_region_obligations(); + assert!( + pre_obligations.is_empty(), + "there should be no incoming region obligations = {pre_obligations:#?}", + ); + debug!(?normalized_inputs_and_output); let mut typeck = TypeChecker { diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index c38c5d4c644..cabcfc9b42b 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -340,6 +340,37 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { self.const_i32(cache_type), ]) } + sym::carrying_mul_add => { + let (size, signed) = fn_args.type_at(0).int_size_and_signed(self.tcx); + + let wide_llty = self.type_ix(size.bits() * 2); + let args = args.as_array().unwrap(); + let [a, b, c, d] = args.map(|a| self.intcast(a.immediate(), wide_llty, signed)); + + let wide = if signed { + let prod = self.unchecked_smul(a, b); + let acc = self.unchecked_sadd(prod, c); + self.unchecked_sadd(acc, d) + } else { + let prod = self.unchecked_umul(a, b); + let acc = self.unchecked_uadd(prod, c); + self.unchecked_uadd(acc, d) + }; + + let narrow_llty = self.type_ix(size.bits()); + let low = self.trunc(wide, narrow_llty); + let bits_const = self.const_uint(wide_llty, size.bits()); + // No need for ashr when signed; LLVM changes it to lshr anyway. + let high = self.lshr(wide, bits_const); + // FIXME: could be `trunc nuw`, even for signed. + let high = self.trunc(high, narrow_llty); + + let pair_llty = self.type_struct(&[narrow_llty, narrow_llty], false); + let pair = self.const_poison(pair_llty); + let pair = self.insert_value(pair, low, 0); + let pair = self.insert_value(pair, high, 1); + pair + } sym::ctlz | sym::ctlz_nonzero | sym::cttz diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 0de0c6a7a89..dca7738daf7 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -17,6 +17,7 @@ #![feature(iter_intersperse)] #![feature(let_chains)] #![feature(rustdoc_internals)] +#![feature(slice_as_array)] #![feature(try_blocks)] #![warn(unreachable_pub)] // tidy-alphabetical-end diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 39479401910..427ef141c72 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -94,6 +94,7 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) - | sym::add_with_overflow | sym::sub_with_overflow | sym::mul_with_overflow + | sym::carrying_mul_add | sym::wrapping_add | sym::wrapping_sub | sym::wrapping_mul @@ -436,6 +437,10 @@ pub fn check_intrinsic_type( (1, 0, vec![param(0), param(0)], Ty::new_tup(tcx, &[param(0), tcx.types.bool])) } + sym::carrying_mul_add => { + (2, 0, vec![param(0); 4], Ty::new_tup(tcx, &[param(1), param(0)])) + } + sym::ptr_guaranteed_cmp => ( 1, 0, diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs index 6dce4b2b21d..6496f38269a 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs @@ -299,10 +299,6 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { self.storage.var_infos.len() } - pub fn region_constraint_data(&self) -> &RegionConstraintData<'tcx> { - &self.storage.data - } - /// Takes (and clears) the current set of constraints. Note that /// the set of variables remains intact, but all relationships /// between them are reset. This is used during NLL checking to diff --git a/compiler/rustc_llvm/build.rs b/compiler/rustc_llvm/build.rs index f092110a324..d9d28299413 100644 --- a/compiler/rustc_llvm/build.rs +++ b/compiler/rustc_llvm/build.rs @@ -220,7 +220,7 @@ fn main() { let mut cmd = Command::new(&llvm_config); cmd.arg(llvm_link_arg).arg("--libs"); - // Don't link system libs if cross-compiling unless targetting Windows. + // Don't link system libs if cross-compiling unless targeting Windows. // On Windows system DLLs aren't linked directly, instead import libraries are used. // These import libraries are independent of the host. if !is_crossed || target.contains("windows") { diff --git a/compiler/rustc_mir_build/src/check_tail_calls.rs b/compiler/rustc_mir_build/src/check_tail_calls.rs index b1f46d37d50..0659e3ea314 100644 --- a/compiler/rustc_mir_build/src/check_tail_calls.rs +++ b/compiler/rustc_mir_build/src/check_tail_calls.rs @@ -117,7 +117,7 @@ impl<'tcx> TailCallCkVisitor<'_, 'tcx> { self.report_arguments_mismatch(expr.span, caller_sig, callee_sig); } - // FIXME(explicit_tail_calls): this currenly fails for cases where opaques are used. + // FIXME(explicit_tail_calls): this currently fails for cases where opaques are used. // e.g. // ``` // fn a() -> impl Sized { become b() } // ICE diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index aab4e1b1afc..7df7e732925 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -1336,7 +1336,7 @@ impl<'a> Parser<'a> { ) -> bool { if let ExprKind::Binary(op, l1, r1) = &inner_op.kind { if let ExprKind::Field(_, ident) = l1.kind - && ident.as_str().parse::<i32>().is_err() + && !ident.is_numeric() && !matches!(r1.kind, ExprKind::Lit(_)) { // The parser has encountered `foo.bar<baz`, the likelihood of the turbofish diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 3d202f11722..1b017a07d60 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -555,6 +555,7 @@ symbols! { call_ref_future, caller_location, capture_disjoint_fields, + carrying_mul_add, catch_unwind, cause, cdylib, @@ -2707,6 +2708,12 @@ impl Ident { pub fn is_raw_guess(self) -> bool { self.name.can_be_raw() && self.is_reserved() } + + /// Whether this would be the identifier for a tuple field like `self.0`, as + /// opposed to a named field like `self.thing`. + pub fn is_numeric(self) -> bool { + !self.name.is_empty() && self.as_str().bytes().all(|b| b.is_ascii_digit()) + } } /// Collect all the keywords in a given edition into a vector. diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 6730f28893d..9a53e8a5d51 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -161,8 +161,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { let outlives_env = OutlivesEnvironment::new(full_env); let _ = infcx.process_registered_region_obligations(&outlives_env, |ty, _| Ok(ty)); - let region_data = - infcx.inner.borrow_mut().unwrap_region_constraints().region_constraint_data().clone(); + let region_data = infcx.inner.borrow_mut().unwrap_region_constraints().data().clone(); let vid_to_region = self.map_vid_to_region(®ion_data); diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index d6ac4baf8ad..968dc631e50 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -819,7 +819,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { candidates.vec.push(AutoImplCandidate) } } - ty::Error(_) => {} // do not add an auto trait impl for `ty::Error` for now. + ty::Error(_) => { + candidates.vec.push(AutoImplCandidate); + } } } } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 7857ed95cc7..9e7da5eb368 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1843,7 +1843,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { // a global and a non-global where-clause. // // Our handling of where-bounds is generally fairly messy but necessary for backwards - // compatability, see #50825 for why we need to handle global where-bounds like this. + // compatibility, see #50825 for why we need to handle global where-bounds like this. let is_global = |c: ty::PolyTraitPredicate<'tcx>| c.is_global() && !c.has_bound_vars(); let param_candidates = candidates .iter() |
