diff --git a/RELEASES.md b/RELEASES.md index fe557a08a9dc0..7c2c2406e9062 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -37,7 +37,7 @@ Libraries - [Move `::copysign`, `::abs`, `::signum` to `core`](/~https://github.com/rust-lang/rust/pull/131304) - [Add `LowerExp` and `UpperExp` implementations to `NonZero`](/~https://github.com/rust-lang/rust/pull/131377) - [Implement `FromStr` for `CString` and `TryFrom` for `String`](/~https://github.com/rust-lang/rust/pull/130608) -- [`std::os::darwin` has been made public](/~https://github.com/rust-lang/rust/pull/130635) +- [`std::os::darwin` has been made public](/~https://github.com/rust-lang/rust/pull/123723) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 3a81b93d157ce..8e73df63ef54f 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -623,7 +623,7 @@ impl Pat { PatKind::Wild | PatKind::Rest | PatKind::Never - | PatKind::Lit(_) + | PatKind::Expr(_) | PatKind::Range(..) | PatKind::Ident(..) | PatKind::Path(..) @@ -801,8 +801,8 @@ pub enum PatKind { /// A reference pattern (e.g., `&mut (a, b)`). Ref(P, Mutability), - /// A literal. - Lit(P), + /// A literal, const block or path. + Expr(P), /// A range pattern (e.g., `1...2`, `1..2`, `1..`, `..2`, `1..=2`, `..=2`). Range(Option>, Option>, Spanned), diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 04cdfc93dcb15..aa88e8369d5b6 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -1512,7 +1512,7 @@ pub fn walk_pat(vis: &mut T, pat: &mut P) { vis.visit_ident(ident); visit_opt(sub, |sub| vis.visit_pat(sub)); } - PatKind::Lit(e) => vis.visit_expr(e), + PatKind::Expr(e) => vis.visit_expr(e), PatKind::TupleStruct(qself, path, elems) => { vis.visit_qself(qself); vis.visit_path(path); diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index e99fc7b604e31..1d6d7330757de 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -680,7 +680,7 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) -> V::Res try_visit!(visitor.visit_ident(ident)); visit_opt!(visitor, visit_pat, optional_subpattern); } - PatKind::Lit(expression) => try_visit!(visitor.visit_expr(expression)), + PatKind::Expr(expression) => try_visit!(visitor.visit_expr(expression)), PatKind::Range(lower_bound, upper_bound, _end) => { visit_opt!(visitor, visit_expr, lower_bound); visit_opt!(visitor, visit_expr, upper_bound); diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index d16a3ce390dbe..a76ca6772e52e 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -102,17 +102,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let kind = match &e.kind { ExprKind::Array(exprs) => hir::ExprKind::Array(self.lower_exprs(exprs)), - ExprKind::ConstBlock(c) => { - let c = self.with_new_scopes(c.value.span, |this| { - let def_id = this.local_def_id(c.id); - hir::ConstBlock { - def_id, - hir_id: this.lower_node_id(c.id), - body: this.lower_const_body(c.value.span, Some(&c.value)), - } - }); - hir::ExprKind::ConstBlock(c) - } + ExprKind::ConstBlock(c) => hir::ExprKind::ConstBlock(self.lower_const_block(c)), ExprKind::Repeat(expr, count) => { let expr = self.lower_expr(expr); let count = self.lower_array_length_to_const_arg(count); @@ -153,18 +143,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let ohs = self.lower_expr(ohs); hir::ExprKind::Unary(op, ohs) } - ExprKind::Lit(token_lit) => { - let lit_kind = match LitKind::from_token_lit(*token_lit) { - Ok(lit_kind) => lit_kind, - Err(err) => { - let guar = - report_lit_error(&self.tcx.sess.psess, err, *token_lit, e.span); - LitKind::Err(guar) - } - }; - let lit = self.arena.alloc(respan(self.lower_span(e.span), lit_kind)); - hir::ExprKind::Lit(lit) - } + ExprKind::Lit(token_lit) => hir::ExprKind::Lit(self.lower_lit(token_lit, e.span)), ExprKind::IncludedBytes(bytes) => { let lit = self.arena.alloc(respan( self.lower_span(e.span), @@ -403,6 +382,32 @@ impl<'hir> LoweringContext<'_, 'hir> { }) } + pub(crate) fn lower_const_block(&mut self, c: &AnonConst) -> hir::ConstBlock { + self.with_new_scopes(c.value.span, |this| { + let def_id = this.local_def_id(c.id); + hir::ConstBlock { + def_id, + hir_id: this.lower_node_id(c.id), + body: this.lower_const_body(c.value.span, Some(&c.value)), + } + }) + } + + pub(crate) fn lower_lit( + &mut self, + token_lit: &token::Lit, + span: Span, + ) -> &'hir Spanned { + let lit_kind = match LitKind::from_token_lit(*token_lit) { + Ok(lit_kind) => lit_kind, + Err(err) => { + let guar = report_lit_error(&self.tcx.sess.psess, err, *token_lit, span); + LitKind::Err(guar) + } + }; + self.arena.alloc(respan(self.lower_span(span), lit_kind)) + } + fn lower_unop(&mut self, u: UnOp) -> hir::UnOp { match u { UnOp::Deref => hir::UnOp::Deref, diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs index c3ff7b4b89722..29d4fb9ef2597 100644 --- a/compiler/rustc_ast_lowering/src/index.rs +++ b/compiler/rustc_ast_lowering/src/index.rs @@ -209,6 +209,14 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { }); } + fn visit_pat_expr(&mut self, expr: &'hir PatExpr<'hir>) { + self.insert(expr.span, expr.hir_id, Node::PatExpr(expr)); + + self.with_parent(expr.hir_id, |this| { + intravisit::walk_pat_expr(this, expr); + }); + } + fn visit_pat_field(&mut self, field: &'hir PatField<'hir>) { self.insert(field.span, field.hir_id, Node::PatField(field)); self.with_parent(field.hir_id, |this| { diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index fe2d5a594f312..0e28590bd6609 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -35,6 +35,7 @@ #![doc(rust_logo)] #![feature(assert_matches)] #![feature(box_patterns)] +#![feature(if_let_guard)] #![feature(let_chains)] #![feature(rustdoc_internals)] #![warn(unreachable_pub)] diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index 40e7d6430fde5..abd314ae74c39 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -1,9 +1,12 @@ +use std::sync::Arc; + use rustc_ast::ptr::P; use rustc_ast::*; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir as hir; use rustc_hir::def::Res; -use rustc_span::source_map::Spanned; +use rustc_middle::span_bug; +use rustc_span::source_map::{Spanned, respan}; use rustc_span::{Ident, Span}; use super::errors::{ @@ -35,8 +38,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { lower_sub, ); } - PatKind::Lit(e) => { - break hir::PatKind::Lit(self.lower_expr_within_pat(e, false)); + PatKind::Expr(e) => { + break hir::PatKind::Expr(self.lower_expr_within_pat(e, false)); } PatKind::TupleStruct(qself, path, pats) => { let qpath = self.lower_qpath( @@ -367,24 +370,54 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // } // m!(S); // ``` - fn lower_expr_within_pat(&mut self, expr: &Expr, allow_paths: bool) -> &'hir hir::Expr<'hir> { - match &expr.kind { - ExprKind::Lit(..) - | ExprKind::ConstBlock(..) - | ExprKind::IncludedBytes(..) - | ExprKind::Err(_) - | ExprKind::Dummy => {} - ExprKind::Path(..) if allow_paths => {} - ExprKind::Unary(UnOp::Neg, inner) if matches!(inner.kind, ExprKind::Lit(_)) => {} + fn lower_expr_within_pat( + &mut self, + expr: &Expr, + allow_paths: bool, + ) -> &'hir hir::PatExpr<'hir> { + let err = |guar| hir::PatExprKind::Lit { + lit: self.arena.alloc(respan(self.lower_span(expr.span), LitKind::Err(guar))), + negated: false, + }; + let kind = match &expr.kind { + ExprKind::Lit(lit) => { + hir::PatExprKind::Lit { lit: self.lower_lit(lit, expr.span), negated: false } + } + ExprKind::ConstBlock(c) => hir::PatExprKind::ConstBlock(self.lower_const_block(c)), + ExprKind::IncludedBytes(bytes) => hir::PatExprKind::Lit { + lit: self.arena.alloc(respan( + self.lower_span(expr.span), + LitKind::ByteStr(Arc::clone(bytes), StrStyle::Cooked), + )), + negated: false, + }, + ExprKind::Err(guar) => err(*guar), + ExprKind::Dummy => span_bug!(expr.span, "lowered ExprKind::Dummy"), + ExprKind::Path(qself, path) if allow_paths => hir::PatExprKind::Path(self.lower_qpath( + expr.id, + qself, + path, + ParamMode::Optional, + AllowReturnTypeNotation::No, + ImplTraitContext::Disallowed(ImplTraitPosition::Path), + None, + )), + ExprKind::Unary(UnOp::Neg, inner) if let ExprKind::Lit(lit) = &inner.kind => { + hir::PatExprKind::Lit { lit: self.lower_lit(lit, expr.span), negated: true } + } _ => { let pattern_from_macro = expr.is_approximately_pattern(); let guar = self.dcx().emit_err(ArbitraryExpressionInPattern { span: expr.span, pattern_from_macro_note: pattern_from_macro, }); - return self.arena.alloc(self.expr_err(expr.span, guar)); + err(guar) } - } - self.lower_expr(expr) + }; + self.arena.alloc(hir::PatExpr { + hir_id: self.lower_node_id(expr.id), + span: expr.span, + kind, + }) } } diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 172df10292920..9b958ed6b0d6b 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1701,7 +1701,7 @@ impl<'a> State<'a> { self.print_pat(inner); } } - PatKind::Lit(e) => self.print_expr(e, FixupContext::default()), + PatKind::Expr(e) => self.print_expr(e, FixupContext::default()), PatKind::Range(begin, end, Spanned { node: end_kind, .. }) => { if let Some(e) = begin { self.print_expr(e, FixupContext::default()); diff --git a/compiler/rustc_borrowck/src/consumers.rs b/compiler/rustc_borrowck/src/consumers.rs index 7e8c48a155136..5a89f7c351cf6 100644 --- a/compiler/rustc_borrowck/src/consumers.rs +++ b/compiler/rustc_borrowck/src/consumers.rs @@ -11,8 +11,8 @@ pub use super::dataflow::{BorrowIndex, Borrows, calculate_borrows_out_of_scope_a pub use super::place_ext::PlaceExt; pub use super::places_conflict::{PlaceConflictBias, places_conflict}; pub use super::polonius::legacy::{ - AllFacts as PoloniusInput, LocationTable, PoloniusOutput, PoloniusRegionVid, RichLocation, - RustcFacts, + PoloniusFacts as PoloniusInput, PoloniusLocationTable, PoloniusOutput, PoloniusRegionVid, + RichLocation, RustcFacts, }; pub use super::region_infer::RegionInferenceContext; @@ -33,7 +33,7 @@ pub enum ConsumerOptions { /// without significant slowdowns. /// /// Implies [`RegionInferenceContext`](ConsumerOptions::RegionInferenceContext), - /// and additionally retrieve the [`LocationTable`] and [`PoloniusInput`] that + /// and additionally retrieve the [`PoloniusLocationTable`] and [`PoloniusInput`] that /// would be given to Polonius. Critically, this does not run Polonius, which /// one may want to avoid due to performance issues on large bodies. PoloniusInputFacts, @@ -71,7 +71,7 @@ pub struct BodyWithBorrowckFacts<'tcx> { /// The table that maps Polonius points to locations in the table. /// Populated when using [`ConsumerOptions::PoloniusInputFacts`] /// or [`ConsumerOptions::PoloniusOutputFacts`]. - pub location_table: Option, + pub location_table: Option, /// Polonius input facts. /// Populated when using [`ConsumerOptions::PoloniusInputFacts`] /// or [`ConsumerOptions::PoloniusOutputFacts`]. diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index f90f75141026f..4f46a2cef7c6b 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -60,7 +60,7 @@ use crate::diagnostics::{ use crate::path_utils::*; use crate::place_ext::PlaceExt; use crate::places_conflict::{PlaceConflictBias, places_conflict}; -use crate::polonius::legacy::{LocationTable, PoloniusOutput}; +use crate::polonius::legacy::{PoloniusLocationTable, PoloniusOutput}; use crate::prefixes::PrefixSet; use crate::region_infer::RegionInferenceContext; use crate::renumber::RegionCtxt; @@ -179,7 +179,7 @@ fn do_mir_borrowck<'tcx>( infcx.register_predefined_opaques_for_next_solver(def); } - let location_table = LocationTable::new(body); + let location_table = PoloniusLocationTable::new(body); let move_data = MoveData::gather_moves(body, tcx, |_| true); let promoted_move_data = promoted @@ -250,7 +250,8 @@ fn do_mir_borrowck<'tcx>( infcx: &infcx, body: promoted_body, move_data: &move_data, - location_table: &location_table, // no need to create a real one for the promoted, it is not used + // no need to create a real location table for the promoted, it is not used + location_table: &location_table, movable_coroutine, fn_self_span_reported: Default::default(), locals_are_invalidated_at_exit, @@ -516,7 +517,7 @@ struct MirBorrowckCtxt<'a, 'infcx, 'tcx> { /// Map from MIR `Location` to `LocationIndex`; created /// when MIR borrowck begins. - location_table: &'a LocationTable, + location_table: &'a PoloniusLocationTable, movable_coroutine: bool, /// This keeps track of whether local variables are free-ed when the function diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index 7ae1df9522fb8..aa0bfd7214729 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -28,7 +28,9 @@ use crate::borrow_set::BorrowSet; use crate::consumers::ConsumerOptions; use crate::diagnostics::{BorrowckDiagnosticsBuffer, RegionErrors}; use crate::polonius::LocalizedOutlivesConstraintSet; -use crate::polonius::legacy::{AllFacts, AllFactsExt, LocationTable, PoloniusOutput}; +use crate::polonius::legacy::{ + PoloniusFacts, PoloniusFactsExt, PoloniusLocationTable, PoloniusOutput, +}; use crate::region_infer::RegionInferenceContext; use crate::type_check::{self, MirTypeckResults}; use crate::universal_regions::UniversalRegions; @@ -39,7 +41,7 @@ use crate::{BorrowckInferCtxt, polonius, renumber}; pub(crate) struct NllOutput<'tcx> { pub regioncx: RegionInferenceContext<'tcx>, pub opaque_type_values: FxIndexMap>, - pub polonius_input: Option>, + pub polonius_input: Option>, pub polonius_output: Option>, pub opt_closure_req: Option>, pub nll_errors: RegionErrors<'tcx>, @@ -80,7 +82,7 @@ pub(crate) fn compute_regions<'a, 'tcx>( universal_regions: UniversalRegions<'tcx>, body: &Body<'tcx>, promoted: &IndexSlice>, - location_table: &LocationTable, + location_table: &PoloniusLocationTable, flow_inits: ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>, move_data: &MoveData<'tcx>, borrow_set: &BorrowSet<'tcx>, @@ -91,10 +93,10 @@ pub(crate) fn compute_regions<'a, 'tcx>( || is_polonius_legacy_enabled; let polonius_output = consumer_options.map(|c| c.polonius_output()).unwrap_or_default() || is_polonius_legacy_enabled; - let mut all_facts = - (polonius_input || AllFacts::enabled(infcx.tcx)).then_some(AllFacts::default()); + let mut polonius_facts = + (polonius_input || PoloniusFacts::enabled(infcx.tcx)).then_some(PoloniusFacts::default()); - let elements = Rc::new(DenseLocationMap::new(body)); + let location_map = Rc::new(DenseLocationMap::new(body)); // Run the MIR type-checker. let MirTypeckResults { @@ -109,10 +111,10 @@ pub(crate) fn compute_regions<'a, 'tcx>( universal_regions, location_table, borrow_set, - &mut all_facts, + &mut polonius_facts, flow_inits, move_data, - Rc::clone(&elements), + Rc::clone(&location_map), ); // Create the region inference context, taking ownership of the @@ -122,7 +124,7 @@ pub(crate) fn compute_regions<'a, 'tcx>( // If requested, emit legacy polonius facts. polonius::legacy::emit_facts( - &mut all_facts, + &mut polonius_facts, infcx.tcx, location_table, body, @@ -137,7 +139,7 @@ pub(crate) fn compute_regions<'a, 'tcx>( var_infos, constraints, universal_region_relations, - elements, + location_map, ); // If requested for `-Zpolonius=next`, convert NLL constraints to localized outlives @@ -147,13 +149,13 @@ pub(crate) fn compute_regions<'a, 'tcx>( }); // If requested: dump NLL facts, and run legacy polonius analysis. - let polonius_output = all_facts.as_ref().and_then(|all_facts| { + let polonius_output = polonius_facts.as_ref().and_then(|polonius_facts| { if infcx.tcx.sess.opts.unstable_opts.nll_facts { let def_id = body.source.def_id(); let def_path = infcx.tcx.def_path(def_id); let dir_path = PathBuf::from(&infcx.tcx.sess.opts.unstable_opts.nll_facts_dir) .join(def_path.to_filename_friendly_no_crate()); - all_facts.write_to_dir(dir_path, location_table).unwrap(); + polonius_facts.write_to_dir(dir_path, location_table).unwrap(); } if polonius_output { @@ -162,7 +164,7 @@ pub(crate) fn compute_regions<'a, 'tcx>( let algorithm = Algorithm::from_str(&algorithm).unwrap(); debug!("compute_regions: using polonius algorithm {:?}", algorithm); let _prof_timer = infcx.tcx.prof.generic_activity("polonius_analysis"); - Some(Box::new(Output::compute(all_facts, algorithm, false))) + Some(Box::new(Output::compute(polonius_facts, algorithm, false))) } else { None } @@ -182,7 +184,7 @@ pub(crate) fn compute_regions<'a, 'tcx>( NllOutput { regioncx, opaque_type_values: remapped_opaque_tys, - polonius_input: all_facts.map(Box::new), + polonius_input: polonius_facts.map(Box::new), polonius_output, opt_closure_req: closure_region_requirements, nll_errors, diff --git a/compiler/rustc_borrowck/src/polonius/legacy/accesses.rs b/compiler/rustc_borrowck/src/polonius/legacy/accesses.rs index 4a0c8d9b4b461..edd7ca578b727 100644 --- a/compiler/rustc_borrowck/src/polonius/legacy/accesses.rs +++ b/compiler/rustc_borrowck/src/polonius/legacy/accesses.rs @@ -4,16 +4,16 @@ use rustc_middle::ty::TyCtxt; use rustc_mir_dataflow::move_paths::{LookupResult, MoveData}; use tracing::debug; -use super::{AllFacts, LocationIndex, LocationTable}; +use super::{LocationIndex, PoloniusFacts, PoloniusLocationTable}; use crate::def_use::{self, DefUse}; use crate::universal_regions::UniversalRegions; /// Emit polonius facts for variable defs, uses, drops, and path accesses. pub(crate) fn emit_access_facts<'tcx>( tcx: TyCtxt<'tcx>, - facts: &mut AllFacts, + facts: &mut PoloniusFacts, body: &Body<'tcx>, - location_table: &LocationTable, + location_table: &PoloniusLocationTable, move_data: &MoveData<'tcx>, universal_regions: &UniversalRegions<'tcx>, ) { @@ -31,9 +31,9 @@ pub(crate) fn emit_access_facts<'tcx>( /// MIR visitor extracting point-wise facts about accesses. struct AccessFactsExtractor<'a, 'tcx> { - facts: &'a mut AllFacts, + facts: &'a mut PoloniusFacts, move_data: &'a MoveData<'tcx>, - location_table: &'a LocationTable, + location_table: &'a PoloniusLocationTable, } impl<'tcx> AccessFactsExtractor<'_, 'tcx> { diff --git a/compiler/rustc_borrowck/src/polonius/legacy/facts.rs b/compiler/rustc_borrowck/src/polonius/legacy/facts.rs index 42c4e73321833..64389b11a651a 100644 --- a/compiler/rustc_borrowck/src/polonius/legacy/facts.rs +++ b/compiler/rustc_borrowck/src/polonius/legacy/facts.rs @@ -4,13 +4,13 @@ use std::fs::{self, File}; use std::io::Write; use std::path::Path; -use polonius_engine::{AllFacts as PoloniusFacts, Atom, Output}; +use polonius_engine::{AllFacts, Atom, Output}; use rustc_macros::extension; use rustc_middle::mir::Local; use rustc_middle::ty::{RegionVid, TyCtxt}; use rustc_mir_dataflow::move_paths::MovePathIndex; -use super::{LocationIndex, LocationTable}; +use super::{LocationIndex, PoloniusLocationTable}; use crate::BorrowIndex; #[derive(Copy, Clone, Debug)] @@ -49,11 +49,11 @@ impl polonius_engine::FactTypes for RustcFacts { type Path = MovePathIndex; } -pub type AllFacts = PoloniusFacts; +pub type PoloniusFacts = AllFacts; -#[extension(pub(crate) trait AllFactsExt)] -impl AllFacts { - /// Returns `true` if there is a need to gather `AllFacts` given the +#[extension(pub(crate) trait PoloniusFactsExt)] +impl PoloniusFacts { + /// Returns `true` if there is a need to gather `PoloniusFacts` given the /// current `-Z` flags. fn enabled(tcx: TyCtxt<'_>) -> bool { tcx.sess.opts.unstable_opts.nll_facts @@ -63,7 +63,7 @@ impl AllFacts { fn write_to_dir( &self, dir: impl AsRef, - location_table: &LocationTable, + location_table: &PoloniusLocationTable, ) -> Result<(), Box> { let dir: &Path = dir.as_ref(); fs::create_dir_all(dir)?; @@ -119,7 +119,7 @@ impl Atom for LocationIndex { } struct FactWriter<'w> { - location_table: &'w LocationTable, + location_table: &'w PoloniusLocationTable, dir: &'w Path, } @@ -141,7 +141,7 @@ trait FactRow { fn write( &self, out: &mut dyn Write, - location_table: &LocationTable, + location_table: &PoloniusLocationTable, ) -> Result<(), Box>; } @@ -149,7 +149,7 @@ impl FactRow for PoloniusRegionVid { fn write( &self, out: &mut dyn Write, - location_table: &LocationTable, + location_table: &PoloniusLocationTable, ) -> Result<(), Box> { write_row(out, location_table, &[self]) } @@ -163,7 +163,7 @@ where fn write( &self, out: &mut dyn Write, - location_table: &LocationTable, + location_table: &PoloniusLocationTable, ) -> Result<(), Box> { write_row(out, location_table, &[&self.0, &self.1]) } @@ -178,7 +178,7 @@ where fn write( &self, out: &mut dyn Write, - location_table: &LocationTable, + location_table: &PoloniusLocationTable, ) -> Result<(), Box> { write_row(out, location_table, &[&self.0, &self.1, &self.2]) } @@ -194,7 +194,7 @@ where fn write( &self, out: &mut dyn Write, - location_table: &LocationTable, + location_table: &PoloniusLocationTable, ) -> Result<(), Box> { write_row(out, location_table, &[&self.0, &self.1, &self.2, &self.3]) } @@ -202,7 +202,7 @@ where fn write_row( out: &mut dyn Write, - location_table: &LocationTable, + location_table: &PoloniusLocationTable, columns: &[&dyn FactCell], ) -> Result<(), Box> { for (index, c) in columns.iter().enumerate() { @@ -213,41 +213,41 @@ fn write_row( } trait FactCell { - fn to_string(&self, location_table: &LocationTable) -> String; + fn to_string(&self, location_table: &PoloniusLocationTable) -> String; } impl FactCell for BorrowIndex { - fn to_string(&self, _location_table: &LocationTable) -> String { + fn to_string(&self, _location_table: &PoloniusLocationTable) -> String { format!("{self:?}") } } impl FactCell for Local { - fn to_string(&self, _location_table: &LocationTable) -> String { + fn to_string(&self, _location_table: &PoloniusLocationTable) -> String { format!("{self:?}") } } impl FactCell for MovePathIndex { - fn to_string(&self, _location_table: &LocationTable) -> String { + fn to_string(&self, _location_table: &PoloniusLocationTable) -> String { format!("{self:?}") } } impl FactCell for PoloniusRegionVid { - fn to_string(&self, _location_table: &LocationTable) -> String { + fn to_string(&self, _location_table: &PoloniusLocationTable) -> String { format!("{self:?}") } } impl FactCell for RegionVid { - fn to_string(&self, _location_table: &LocationTable) -> String { + fn to_string(&self, _location_table: &PoloniusLocationTable) -> String { format!("{self:?}") } } impl FactCell for LocationIndex { - fn to_string(&self, location_table: &LocationTable) -> String { + fn to_string(&self, location_table: &PoloniusLocationTable) -> String { format!("{:?}", location_table.to_rich_location(*self)) } } diff --git a/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs b/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs index 3c3b93cdc0d3b..0ad91ae51a3a0 100644 --- a/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs +++ b/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs @@ -11,7 +11,7 @@ use rustc_middle::mir::{ use rustc_middle::ty::TyCtxt; use tracing::debug; -use super::{AllFacts, LocationTable}; +use super::{PoloniusFacts, PoloniusLocationTable}; use crate::borrow_set::BorrowSet; use crate::path_utils::*; use crate::{ @@ -22,9 +22,9 @@ use crate::{ /// Emit `loan_invalidated_at` facts. pub(super) fn emit_loan_invalidations<'tcx>( tcx: TyCtxt<'tcx>, - facts: &mut AllFacts, + facts: &mut PoloniusFacts, body: &Body<'tcx>, - location_table: &LocationTable, + location_table: &PoloniusLocationTable, borrow_set: &BorrowSet<'tcx>, ) { let dominators = body.basic_blocks.dominators(); @@ -35,9 +35,9 @@ pub(super) fn emit_loan_invalidations<'tcx>( struct LoanInvalidationsGenerator<'a, 'tcx> { tcx: TyCtxt<'tcx>, - facts: &'a mut AllFacts, + facts: &'a mut PoloniusFacts, body: &'a Body<'tcx>, - location_table: &'a LocationTable, + location_table: &'a PoloniusLocationTable, dominators: &'a Dominators, borrow_set: &'a BorrowSet<'tcx>, } diff --git a/compiler/rustc_borrowck/src/polonius/legacy/loan_kills.rs b/compiler/rustc_borrowck/src/polonius/legacy/loan_kills.rs index 0148e0b286967..098c922bf7b91 100644 --- a/compiler/rustc_borrowck/src/polonius/legacy/loan_kills.rs +++ b/compiler/rustc_borrowck/src/polonius/legacy/loan_kills.rs @@ -6,16 +6,16 @@ use rustc_middle::mir::{ use rustc_middle::ty::TyCtxt; use tracing::debug; -use super::{AllFacts, LocationTable}; +use super::{PoloniusFacts, PoloniusLocationTable}; use crate::borrow_set::BorrowSet; use crate::places_conflict; /// Emit `loan_killed_at` and `cfg_edge` facts at the same time. pub(super) fn emit_loan_kills<'tcx>( tcx: TyCtxt<'tcx>, - facts: &mut AllFacts, + facts: &mut PoloniusFacts, body: &Body<'tcx>, - location_table: &LocationTable, + location_table: &PoloniusLocationTable, borrow_set: &BorrowSet<'tcx>, ) { let mut visitor = LoanKillsGenerator { borrow_set, tcx, location_table, facts, body }; @@ -26,8 +26,8 @@ pub(super) fn emit_loan_kills<'tcx>( struct LoanKillsGenerator<'a, 'tcx> { tcx: TyCtxt<'tcx>, - facts: &'a mut AllFacts, - location_table: &'a LocationTable, + facts: &'a mut PoloniusFacts, + location_table: &'a PoloniusLocationTable, borrow_set: &'a BorrowSet<'tcx>, body: &'a Body<'tcx>, } diff --git a/compiler/rustc_borrowck/src/polonius/legacy/location.rs b/compiler/rustc_borrowck/src/polonius/legacy/location.rs index 4cb1202033cb9..5f816bb9bbdc4 100644 --- a/compiler/rustc_borrowck/src/polonius/legacy/location.rs +++ b/compiler/rustc_borrowck/src/polonius/legacy/location.rs @@ -13,7 +13,7 @@ use tracing::debug; /// granularity through outlives relations; however, the rich location /// table serves another purpose: it compresses locations from /// multiple words into a single u32. -pub struct LocationTable { +pub struct PoloniusLocationTable { num_points: usize, statements_before_block: IndexVec, } @@ -30,7 +30,7 @@ pub enum RichLocation { Mid(Location), } -impl LocationTable { +impl PoloniusLocationTable { pub(crate) fn new(body: &Body<'_>) -> Self { let mut num_points = 0; let statements_before_block = body @@ -43,8 +43,8 @@ impl LocationTable { }) .collect(); - debug!("LocationTable(statements_before_block={:#?})", statements_before_block); - debug!("LocationTable: num_points={:#?}", num_points); + debug!("PoloniusLocationTable(statements_before_block={:#?})", statements_before_block); + debug!("PoloniusLocationTable: num_points={:#?}", num_points); Self { num_points, statements_before_block } } diff --git a/compiler/rustc_borrowck/src/polonius/legacy/mod.rs b/compiler/rustc_borrowck/src/polonius/legacy/mod.rs index 45bdbd1e9997e..95820c07a02f8 100644 --- a/compiler/rustc_borrowck/src/polonius/legacy/mod.rs +++ b/compiler/rustc_borrowck/src/polonius/legacy/mod.rs @@ -36,16 +36,16 @@ pub use self::facts::*; /// /// The rest of the facts are emitted during typeck and liveness. pub(crate) fn emit_facts<'tcx>( - all_facts: &mut Option, + facts: &mut Option, tcx: TyCtxt<'tcx>, - location_table: &LocationTable, + location_table: &PoloniusLocationTable, body: &Body<'tcx>, borrow_set: &BorrowSet<'tcx>, move_data: &MoveData<'tcx>, universal_region_relations: &UniversalRegionRelations<'tcx>, constraints: &MirTypeckRegionConstraints<'tcx>, ) { - let Some(facts) = all_facts else { + let Some(facts) = facts else { // We don't do anything if there are no facts to fill. return; }; @@ -67,9 +67,9 @@ pub(crate) fn emit_facts<'tcx>( /// Emit facts needed for move/init analysis: moves and assignments. fn emit_move_facts( - facts: &mut AllFacts, + facts: &mut PoloniusFacts, body: &Body<'_>, - location_table: &LocationTable, + location_table: &PoloniusLocationTable, move_data: &MoveData<'_>, ) { facts.path_is_var.extend(move_data.rev_lookup.iter_locals_enumerated().map(|(l, r)| (r, l))); @@ -139,7 +139,7 @@ fn emit_move_facts( /// Emit universal regions facts, and their relations. fn emit_universal_region_facts( - facts: &mut AllFacts, + facts: &mut PoloniusFacts, borrow_set: &BorrowSet<'_>, universal_region_relations: &UniversalRegionRelations<'_>, ) { @@ -187,10 +187,10 @@ pub(crate) fn emit_drop_facts<'tcx>( local: Local, kind: &GenericArg<'tcx>, universal_regions: &UniversalRegions<'tcx>, - all_facts: &mut Option, + facts: &mut Option, ) { debug!("emit_drop_facts(local={:?}, kind={:?}", local, kind); - let Some(facts) = all_facts.as_mut() else { return }; + let Some(facts) = facts.as_mut() else { return }; let _prof_timer = tcx.prof.generic_activity("polonius_fact_generation"); tcx.for_each_free_region(kind, |drop_live_region| { let region_vid = universal_regions.to_region_vid(drop_live_region); @@ -201,8 +201,8 @@ pub(crate) fn emit_drop_facts<'tcx>( /// Emit facts about the outlives constraints: the `subset` base relation, i.e. not a transitive /// closure. fn emit_outlives_facts<'tcx>( - facts: &mut AllFacts, - location_table: &LocationTable, + facts: &mut PoloniusFacts, + location_table: &PoloniusLocationTable, constraints: &MirTypeckRegionConstraints<'tcx>, ) { facts.subset_base.extend(constraints.outlives_constraints.outlives().iter().flat_map( diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 59189082f6fc9..c177538ee177a 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -392,7 +392,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { var_infos: VarInfos, constraints: MirTypeckRegionConstraints<'tcx>, universal_region_relations: Frozen>, - elements: Rc, + location_map: Rc, ) -> Self { let universal_regions = &universal_region_relations.universal_regions; let MirTypeckRegionConstraints { @@ -436,7 +436,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { } let mut scc_values = - RegionValues::new(elements, universal_regions.len(), placeholder_indices); + RegionValues::new(location_map, universal_regions.len(), placeholder_indices); for region in liveness_constraints.regions() { let scc = constraint_sccs.scc(region); diff --git a/compiler/rustc_borrowck/src/region_infer/values.rs b/compiler/rustc_borrowck/src/region_infer/values.rs index 75aef8b303ba8..11fb125ca2281 100644 --- a/compiler/rustc_borrowck/src/region_infer/values.rs +++ b/compiler/rustc_borrowck/src/region_infer/values.rs @@ -38,7 +38,7 @@ pub(crate) enum RegionElement { /// an interval matrix storing liveness ranges for each region-vid. pub(crate) struct LivenessValues { /// The map from locations to points. - elements: Rc, + location_map: Rc, /// Which regions are live. This is exclusive with the fine-grained tracking in `points`, and /// currently only used for validating promoteds (which don't care about more precise tracking). @@ -77,11 +77,11 @@ impl LiveLoans { impl LivenessValues { /// Create an empty map of regions to locations where they're live. - pub(crate) fn with_specific_points(elements: Rc) -> Self { + pub(crate) fn with_specific_points(location_map: Rc) -> Self { LivenessValues { live_regions: None, - points: Some(SparseIntervalMatrix::new(elements.num_points())), - elements, + points: Some(SparseIntervalMatrix::new(location_map.num_points())), + location_map, loans: None, } } @@ -90,11 +90,11 @@ impl LivenessValues { /// /// Unlike `with_specific_points`, does not track exact locations where something is live, only /// which regions are live. - pub(crate) fn without_specific_points(elements: Rc) -> Self { + pub(crate) fn without_specific_points(location_map: Rc) -> Self { LivenessValues { live_regions: Some(Default::default()), points: None, - elements, + location_map, loans: None, } } @@ -122,11 +122,11 @@ impl LivenessValues { /// Records `region` as being live at the given `location`. pub(crate) fn add_location(&mut self, region: RegionVid, location: Location) { - let point = self.elements.point_from_location(location); + let point = self.location_map.point_from_location(location); debug!("LivenessValues::add_location(region={:?}, location={:?})", region, location); if let Some(points) = &mut self.points { points.insert(region, point); - } else if self.elements.point_in_range(point) { + } else if self.location_map.point_in_range(point) { self.live_regions.as_mut().unwrap().insert(region); } @@ -143,7 +143,7 @@ impl LivenessValues { debug!("LivenessValues::add_points(region={:?}, points={:?})", region, points); if let Some(this) = &mut self.points { this.union_row(region, points); - } else if points.iter().any(|point| self.elements.point_in_range(point)) { + } else if points.iter().any(|point| self.location_map.point_in_range(point)) { self.live_regions.as_mut().unwrap().insert(region); } @@ -170,7 +170,7 @@ impl LivenessValues { /// Returns whether `region` is marked live at the given `location`. pub(crate) fn is_live_at(&self, region: RegionVid, location: Location) -> bool { - let point = self.elements.point_from_location(location); + let point = self.location_map.point_from_location(location); if let Some(points) = &self.points { points.row(region).is_some_and(|r| r.contains(point)) } else { @@ -191,25 +191,26 @@ impl LivenessValues { .row(region) .into_iter() .flat_map(|set| set.iter()) - .take_while(|&p| self.elements.point_in_range(p)) + .take_while(|&p| self.location_map.point_in_range(p)) } /// For debugging purposes, returns a pretty-printed string of the points where the `region` is /// live. pub(crate) fn pretty_print_live_points(&self, region: RegionVid) -> String { pretty_print_region_elements( - self.live_points(region).map(|p| RegionElement::Location(self.elements.to_location(p))), + self.live_points(region) + .map(|p| RegionElement::Location(self.location_map.to_location(p))), ) } #[inline] pub(crate) fn point_from_location(&self, location: Location) -> PointIndex { - self.elements.point_from_location(location) + self.location_map.point_from_location(location) } #[inline] pub(crate) fn location_from_point(&self, point: PointIndex) -> Location { - self.elements.to_location(point) + self.location_map.to_location(point) } /// When using `-Zpolonius=next`, returns whether the `loan_idx` is live at the given `point`. @@ -272,7 +273,7 @@ impl PlaceholderIndices { /// because (since it is returned) it must live for at least `'a`. But /// it would also contain various points from within the function. pub(crate) struct RegionValues { - elements: Rc, + location_map: Rc, placeholder_indices: PlaceholderIndices, points: SparseIntervalMatrix, free_regions: SparseBitMatrix, @@ -287,14 +288,14 @@ impl RegionValues { /// Each of the regions in num_region_variables will be initialized with an /// empty set of points and no causal information. pub(crate) fn new( - elements: Rc, + location_map: Rc, num_universal_regions: usize, placeholder_indices: PlaceholderIndices, ) -> Self { - let num_points = elements.num_points(); + let num_points = location_map.num_points(); let num_placeholders = placeholder_indices.len(); Self { - elements, + location_map, points: SparseIntervalMatrix::new(num_points), placeholder_indices, free_regions: SparseBitMatrix::new(num_universal_regions), @@ -336,7 +337,7 @@ impl RegionValues { end: usize, ) -> Option { let row = self.points.row(r)?; - let block = self.elements.entry_point(block); + let block = self.location_map.entry_point(block); let start = block.plus(start); let end = block.plus(end); let first_unset = row.first_unset_in(start..=end)?; @@ -375,8 +376,8 @@ impl RegionValues { pub(crate) fn locations_outlived_by<'a>(&'a self, r: N) -> impl Iterator + 'a { self.points.row(r).into_iter().flat_map(move |set| { set.iter() - .take_while(move |&p| self.elements.point_in_range(p)) - .map(move |p| self.elements.to_location(p)) + .take_while(move |&p| self.location_map.point_in_range(p)) + .map(move |p| self.location_map.to_location(p)) }) } @@ -430,12 +431,12 @@ pub(crate) trait ToElementIndex: Debug + Copy { impl ToElementIndex for Location { fn add_to_row(self, values: &mut RegionValues, row: N) -> bool { - let index = values.elements.point_from_location(self); + let index = values.location_map.point_from_location(self); values.points.insert(row, index) } fn contained_in_row(self, values: &RegionValues, row: N) -> bool { - let index = values.elements.point_from_location(self); + let index = values.location_map.point_from_location(self); values.points.contains(row, index) } } @@ -464,14 +465,14 @@ impl ToElementIndex for ty::PlaceholderRegion { /// For debugging purposes, returns a pretty-printed string of the given points. pub(crate) fn pretty_print_points( - elements: &DenseLocationMap, + location_map: &DenseLocationMap, points: impl IntoIterator, ) -> String { pretty_print_region_elements( points .into_iter() - .take_while(|&p| elements.point_in_range(p)) - .map(|p| elements.to_location(p)) + .take_while(|&p| location_map.point_in_range(p)) + .map(|p| location_map.to_location(p)) .map(RegionElement::Location), ) } diff --git a/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs b/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs index 695a1cdac0d79..6182b68f6f411 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs @@ -82,7 +82,7 @@ impl<'a> Iterator for AppearancesIter<'a> { impl LocalUseMap { pub(crate) fn build( live_locals: &[Local], - elements: &DenseLocationMap, + location_map: &DenseLocationMap, body: &Body<'_>, ) -> Self { let nones = IndexVec::from_elem(None, &body.local_decls); @@ -101,7 +101,7 @@ impl LocalUseMap { IndexVec::from_elem(false, &body.local_decls); live_locals.iter().for_each(|&local| locals_with_use_data[local] = true); - LocalUseMapBuild { local_use_map: &mut local_use_map, elements, locals_with_use_data } + LocalUseMapBuild { local_use_map: &mut local_use_map, location_map, locals_with_use_data } .visit_body(body); local_use_map @@ -125,7 +125,7 @@ impl LocalUseMap { struct LocalUseMapBuild<'me> { local_use_map: &'me mut LocalUseMap, - elements: &'me DenseLocationMap, + location_map: &'me DenseLocationMap, // Vector used in `visit_local` to signal which `Local`s do we need // def/use/drop information on, constructed from `live_locals` (that @@ -147,7 +147,7 @@ impl Visitor<'_> for LocalUseMapBuild<'_> { DefUse::Use => &mut self.local_use_map.first_use_at[local], DefUse::Drop => &mut self.local_use_map.first_drop_at[local], }; - let point_index = self.elements.point_from_location(location); + let point_index = self.location_map.point_from_location(location); let appearance_index = self .local_use_map .appearances diff --git a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs index 3e9900cce5f57..f23602d03588f 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs @@ -32,7 +32,7 @@ mod trace; pub(super) fn generate<'a, 'tcx>( typeck: &mut TypeChecker<'_, 'tcx>, body: &Body<'tcx>, - elements: &DenseLocationMap, + location_map: &DenseLocationMap, flow_inits: ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>, move_data: &MoveData<'tcx>, ) { @@ -49,7 +49,7 @@ pub(super) fn generate<'a, 'tcx>( trace::trace( typeck, body, - elements, + location_map, flow_inits, move_data, relevant_live_locals, diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs index c7a2d32b31dc8..7fce49fd16bb9 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs @@ -37,13 +37,13 @@ use crate::type_check::{NormalizeLocation, TypeChecker}; pub(super) fn trace<'a, 'tcx>( typeck: &mut TypeChecker<'_, 'tcx>, body: &Body<'tcx>, - elements: &DenseLocationMap, + location_map: &DenseLocationMap, flow_inits: ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>, move_data: &MoveData<'tcx>, relevant_live_locals: Vec, boring_locals: Vec, ) { - let local_use_map = &LocalUseMap::build(&relevant_live_locals, elements, body); + let local_use_map = &LocalUseMap::build(&relevant_live_locals, location_map, body); // When using `-Zpolonius=next`, compute the set of loans that can reach a given region. if typeck.tcx().sess.opts.unstable_opts.polonius.is_next_enabled() { @@ -79,7 +79,7 @@ pub(super) fn trace<'a, 'tcx>( typeck, body, flow_inits, - elements, + location_map, local_use_map, move_data, drop_data: FxIndexMap::default(), @@ -100,7 +100,7 @@ struct LivenessContext<'a, 'typeck, 'b, 'tcx> { typeck: &'a mut TypeChecker<'typeck, 'tcx>, /// Defines the `PointIndex` mapping - elements: &'a DenseLocationMap, + location_map: &'a DenseLocationMap, /// MIR we are analyzing. body: &'a Body<'tcx>, @@ -149,7 +149,7 @@ struct LivenessResults<'a, 'typeck, 'b, 'tcx> { impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> { fn new(cx: LivenessContext<'a, 'typeck, 'b, 'tcx>) -> Self { - let num_points = cx.elements.num_points(); + let num_points = cx.location_map.num_points(); LivenessResults { cx, defs: BitSet::new_empty(num_points), @@ -213,14 +213,14 @@ impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> { fn add_extra_drop_facts(&mut self, relevant_live_locals: &[Local]) { // This collect is more necessary than immediately apparent // because these facts go into `add_drop_live_facts_for()`, - // which also writes to `all_facts`, and so this is genuinely + // which also writes to `polonius_facts`, and so this is genuinely // a simultaneous overlapping mutable borrow. // FIXME for future hackers: investigate whether this is // actually necessary; these facts come from Polonius // and probably maybe plausibly does not need to go back in. // It may be necessary to just pick out the parts of // `add_drop_live_facts_for()` that make sense. - let Some(facts) = self.cx.typeck.all_facts.as_ref() else { return }; + let Some(facts) = self.cx.typeck.polonius_facts.as_ref() else { return }; let facts_to_add: Vec<_> = { let relevant_live_locals: FxIndexSet<_> = relevant_live_locals.iter().copied().collect(); @@ -240,7 +240,7 @@ impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> { .collect() }; - let live_at = IntervalSet::new(self.cx.elements.num_points()); + let live_at = IntervalSet::new(self.cx.location_map.num_points()); for (local, local_ty, location) in facts_to_add { self.cx.add_drop_live_facts_for(local, local_ty, &[location], &live_at); } @@ -279,7 +279,7 @@ impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> { // * Inclusively, the block start // * Exclusively, the previous definition (if it's in this block) // * Exclusively, the previous live_at setting (an optimization) - let block_start = self.cx.elements.to_block_start(p); + let block_start = self.cx.location_map.to_block_start(p); let previous_defs = self.defs.last_set_in(block_start..=p); let previous_live_at = self.use_live_at.last_set_in(block_start..=p); @@ -303,12 +303,12 @@ impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> { // terminators of predecessor basic blocks. Push those onto the // stack so that the next iteration(s) will process them. - let block = self.cx.elements.to_location(block_start).block; + let block = self.cx.location_map.to_location(block_start).block; self.stack.extend( self.cx.body.basic_blocks.predecessors()[block] .iter() .map(|&pred_bb| self.cx.body.terminator_loc(pred_bb)) - .map(|pred_loc| self.cx.elements.point_from_location(pred_loc)), + .map(|pred_loc| self.cx.location_map.point_from_location(pred_loc)), ); } } @@ -331,7 +331,7 @@ impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> { // Find the drops where `local` is initialized. for drop_point in self.cx.local_use_map.drops(local) { - let location = self.cx.elements.to_location(drop_point); + let location = self.cx.location_map.to_location(drop_point); debug_assert_eq!(self.cx.body.terminator_loc(location.block), location,); if self.cx.initialized_at_terminator(location.block, mpi) @@ -367,7 +367,7 @@ impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> { debug!( "compute_drop_live_points_for_block(mpi={:?}, term_point={:?})", self.cx.move_data.move_paths[mpi].place, - self.cx.elements.to_location(term_point), + self.cx.location_map.to_location(term_point), ); // We are only invoked with terminators where `mpi` is @@ -377,12 +377,15 @@ impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> { // Otherwise, scan backwards through the statements in the // block. One of them may be either a definition or use // live point. - let term_location = self.cx.elements.to_location(term_point); + let term_location = self.cx.location_map.to_location(term_point); debug_assert_eq!(self.cx.body.terminator_loc(term_location.block), term_location,); let block = term_location.block; - let entry_point = self.cx.elements.entry_point(term_location.block); + let entry_point = self.cx.location_map.entry_point(term_location.block); for p in (entry_point..term_point).rev() { - debug!("compute_drop_live_points_for_block: p = {:?}", self.cx.elements.to_location(p)); + debug!( + "compute_drop_live_points_for_block: p = {:?}", + self.cx.location_map.to_location(p) + ); if self.defs.contains(p) { debug!("compute_drop_live_points_for_block: def site"); @@ -428,7 +431,7 @@ impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> { } let pred_term_loc = self.cx.body.terminator_loc(pred_block); - let pred_term_point = self.cx.elements.point_from_location(pred_term_loc); + let pred_term_point = self.cx.location_map.point_from_location(pred_term_loc); // If the terminator of this predecessor either *assigns* // our value or is a "normal use", then stop. @@ -523,7 +526,7 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> { /// points `live_at`. fn add_use_live_facts_for(&mut self, value: Ty<'tcx>, live_at: &IntervalSet) { debug!("add_use_live_facts_for(value={:?})", value); - Self::make_all_regions_live(self.elements, self.typeck, value, live_at); + Self::make_all_regions_live(self.location_map, self.typeck, value, live_at); } /// Some variable with type `live_ty` is "drop live" at `location` @@ -547,7 +550,7 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> { dropped_local, dropped_ty, drop_locations, - values::pretty_print_points(self.elements, live_at.iter()), + values::pretty_print_points(self.location_map, live_at.iter()), ); let drop_data = self.drop_data.entry(dropped_ty).or_insert_with({ @@ -574,19 +577,19 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> { // All things in the `outlives` array may be touched by // the destructor and must be live at this point. for &kind in &drop_data.dropck_result.kinds { - Self::make_all_regions_live(self.elements, self.typeck, kind, live_at); + Self::make_all_regions_live(self.location_map, self.typeck, kind, live_at); polonius::legacy::emit_drop_facts( self.typeck.tcx(), dropped_local, &kind, self.typeck.universal_regions, - self.typeck.all_facts, + self.typeck.polonius_facts, ); } } fn make_all_regions_live( - elements: &DenseLocationMap, + location_map: &DenseLocationMap, typeck: &mut TypeChecker<'_, 'tcx>, value: impl TypeVisitable> + Relate>, live_at: &IntervalSet, @@ -594,7 +597,7 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> { debug!("make_all_regions_live(value={:?})", value); debug!( "make_all_regions_live: live_at={}", - values::pretty_print_points(elements, live_at.iter()), + values::pretty_print_points(location_map, live_at.iter()), ); value.visit_with(&mut for_liveness::FreeRegionsVisitor { diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 1eb471968b285..889b5684a2120 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -49,7 +49,7 @@ use crate::constraints::{OutlivesConstraint, OutlivesConstraintSet}; use crate::diagnostics::UniverseInfo; use crate::member_constraints::MemberConstraintSet; use crate::polonius::PoloniusContext; -use crate::polonius::legacy::{AllFacts, LocationTable}; +use crate::polonius::legacy::{PoloniusFacts, PoloniusLocationTable}; use crate::region_infer::TypeTest; use crate::region_infer::values::{LivenessValues, PlaceholderIndex, PlaceholderIndices}; use crate::renumber::RegionCtxt; @@ -98,29 +98,29 @@ mod relate_tys; /// - `body` -- MIR body to type-check /// - `promoted` -- map of promoted constants within `body` /// - `universal_regions` -- the universal regions from `body`s function signature -/// - `location_table` -- MIR location map of `body` +/// - `location_table` -- for datalog polonius, the map between `Location`s and `RichLocation`s /// - `borrow_set` -- information about borrows occurring in `body` -/// - `all_facts` -- when using Polonius, this is the generated set of Polonius facts +/// - `polonius_facts` -- when using Polonius, this is the generated set of Polonius facts /// - `flow_inits` -- results of a maybe-init dataflow analysis /// - `move_data` -- move-data constructed when performing the maybe-init dataflow analysis -/// - `elements` -- MIR region map +/// - `location_map` -- map between MIR `Location` and `PointIndex` pub(crate) fn type_check<'a, 'tcx>( infcx: &BorrowckInferCtxt<'tcx>, body: &Body<'tcx>, promoted: &IndexSlice>, universal_regions: UniversalRegions<'tcx>, - location_table: &LocationTable, + location_table: &PoloniusLocationTable, borrow_set: &BorrowSet<'tcx>, - all_facts: &mut Option, + polonius_facts: &mut Option, flow_inits: ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>, move_data: &MoveData<'tcx>, - elements: Rc, + location_map: Rc, ) -> MirTypeckResults<'tcx> { let implicit_region_bound = ty::Region::new_var(infcx.tcx, universal_regions.fr_fn_body); let mut constraints = MirTypeckRegionConstraints { placeholder_indices: PlaceholderIndices::default(), placeholder_index_to_region: IndexVec::default(), - liveness_constraints: LivenessValues::with_specific_points(Rc::clone(&elements)), + liveness_constraints: LivenessValues::with_specific_points(Rc::clone(&location_map)), outlives_constraints: OutlivesConstraintSet::default(), member_constraints: MemberConstraintSet::default(), type_tests: Vec::default(), @@ -165,7 +165,7 @@ pub(crate) fn type_check<'a, 'tcx>( reported_errors: Default::default(), universal_regions: &universal_region_relations.universal_regions, location_table, - all_facts, + polonius_facts, borrow_set, constraints: &mut constraints, polonius_context: &mut polonius_context, @@ -180,7 +180,7 @@ pub(crate) fn type_check<'a, 'tcx>( typeck.equate_inputs_and_outputs(body, &normalized_inputs_and_output); typeck.check_signature_annotation(body); - liveness::generate(&mut typeck, body, &elements, flow_inits, move_data); + liveness::generate(&mut typeck, body, &location_map, flow_inits, move_data); let opaque_type_values = opaque_types::take_opaques_and_register_member_constraints(&mut typeck); @@ -495,14 +495,14 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { // Use new sets of constraints and closure bounds so that we can // modify their locations. - let all_facts = &mut None; + let polonius_facts = &mut None; let mut constraints = Default::default(); let mut liveness_constraints = LivenessValues::without_specific_points(Rc::new(DenseLocationMap::new(promoted_body))); // Don't try to add borrow_region facts for the promoted MIR let mut swap_constraints = |this: &mut Self| { - mem::swap(this.typeck.all_facts, all_facts); + mem::swap(this.typeck.polonius_facts, polonius_facts); mem::swap(&mut this.typeck.constraints.outlives_constraints, &mut constraints); mem::swap(&mut this.typeck.constraints.liveness_constraints, &mut liveness_constraints); }; @@ -560,8 +560,8 @@ struct TypeChecker<'a, 'tcx> { implicit_region_bound: ty::Region<'tcx>, reported_errors: FxIndexSet<(Ty<'tcx>, Span)>, universal_regions: &'a UniversalRegions<'tcx>, - location_table: &'a LocationTable, - all_facts: &'a mut Option, + location_table: &'a PoloniusLocationTable, + polonius_facts: &'a mut Option, borrow_set: &'a BorrowSet<'tcx>, constraints: &'a mut MirTypeckRegionConstraints<'tcx>, /// When using `-Zpolonius=next`, the helper data used to create polonius constraints. @@ -2341,18 +2341,18 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { borrowed_place: &Place<'tcx>, ) { // These constraints are only meaningful during borrowck: - let Self { borrow_set, location_table, all_facts, constraints, .. } = self; + let Self { borrow_set, location_table, polonius_facts, constraints, .. } = self; // In Polonius mode, we also push a `loan_issued_at` fact // linking the loan to the region (in some cases, though, // there is no loan associated with this borrow expression -- // that occurs when we are borrowing an unsafe place, for // example). - if let Some(all_facts) = all_facts { + if let Some(polonius_facts) = polonius_facts { let _prof_timer = self.infcx.tcx.prof.generic_activity("polonius_fact_generation"); if let Some(borrow_index) = borrow_set.get_index_of(&location) { let region_vid = borrow_region.as_var(); - all_facts.loan_issued_at.push(( + polonius_facts.loan_issued_at.push(( region_vid.into(), borrow_index, location_table.mid_index(location), diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index e6adbc0f0ac89..43feab94c01d9 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -522,7 +522,7 @@ impl MacResult for MacEager { return Some(P(ast::Pat { id: ast::DUMMY_NODE_ID, span: e.span, - kind: PatKind::Lit(e), + kind: PatKind::Expr(e), tokens: None, })); } diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index 22bfda34cc0e5..8bf09cf96b3f7 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -486,7 +486,7 @@ impl<'a> ExtCtxt<'a> { self.pat(span, PatKind::Wild) } pub fn pat_lit(&self, span: Span, expr: P) -> P { - self.pat(span, PatKind::Lit(expr)) + self.pat(span, PatKind::Expr(expr)) } pub fn pat_ident(&self, span: Span, ident: Ident) -> P { self.pat_ident_binding_mode(span, ident, ast::BindingMode::NONE) diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 2e4b6748731aa..951e95a6385d0 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1386,7 +1386,7 @@ impl<'hir> Pat<'hir> { use PatKind::*; match self.kind { - Wild | Never | Lit(_) | Range(..) | Binding(.., None) | Path(_) | Err(_) => true, + Wild | Never | Expr(_) | Range(..) | Binding(.., None) | Path(_) | Err(_) => true, Box(s) | Deref(s) | Ref(s, _) | Binding(.., Some(s)) | Guard(s, _) => s.walk_short_(it), Struct(_, fields, _) => fields.iter().all(|field| field.pat.walk_short_(it)), TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().all(|p| p.walk_short_(it)), @@ -1413,7 +1413,7 @@ impl<'hir> Pat<'hir> { use PatKind::*; match self.kind { - Wild | Never | Lit(_) | Range(..) | Binding(.., None) | Path(_) | Err(_) => {} + Wild | Never | Expr(_) | Range(..) | Binding(.., None) | Path(_) | Err(_) => {} Box(s) | Deref(s) | Ref(s, _) | Binding(.., Some(s)) | Guard(s, _) => s.walk_(it), Struct(_, fields, _) => fields.iter().for_each(|field| field.pat.walk_(it)), TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().for_each(|p| p.walk_(it)), @@ -1519,6 +1519,26 @@ impl fmt::Debug for DotDotPos { } } +#[derive(Debug, Clone, Copy, HashStable_Generic)] +pub struct PatExpr<'hir> { + pub hir_id: HirId, + pub span: Span, + pub kind: PatExprKind<'hir>, +} + +#[derive(Debug, Clone, Copy, HashStable_Generic)] +pub enum PatExprKind<'hir> { + Lit { + lit: &'hir Lit, + // FIXME: move this into `Lit` and handle negated literal expressions + // once instead of matching on unop neg expressions everywhere. + negated: bool, + }, + ConstBlock(ConstBlock), + /// A path pattern for a unit struct/variant or a (maybe-associated) constant. + Path(QPath<'hir>), +} + #[derive(Debug, Clone, Copy, HashStable_Generic)] pub enum PatKind<'hir> { /// Represents a wildcard pattern (i.e., `_`). @@ -1563,14 +1583,14 @@ pub enum PatKind<'hir> { /// A reference pattern (e.g., `&mut (a, b)`). Ref(&'hir Pat<'hir>, Mutability), - /// A literal. - Lit(&'hir Expr<'hir>), + /// A literal, const block or path. + Expr(&'hir PatExpr<'hir>), /// A guard pattern (e.g., `x if guard(x)`). Guard(&'hir Pat<'hir>, &'hir Expr<'hir>), /// A range pattern (e.g., `1..=2` or `1..2`). - Range(Option<&'hir Expr<'hir>>, Option<&'hir Expr<'hir>>, RangeEnd), + Range(Option<&'hir PatExpr<'hir>>, Option<&'hir PatExpr<'hir>>, RangeEnd), /// A slice pattern, `[before_0, ..., before_n, (slice, after_0, ..., after_n)?]`. /// @@ -4144,6 +4164,10 @@ pub enum Node<'hir> { OpaqueTy(&'hir OpaqueTy<'hir>), Pat(&'hir Pat<'hir>), PatField(&'hir PatField<'hir>), + /// Needed as its own node with its own HirId for tracking + /// the unadjusted type of literals within patterns + /// (e.g. byte str literals not being of slice type). + PatExpr(&'hir PatExpr<'hir>), Arm(&'hir Arm<'hir>), Block(&'hir Block<'hir>), LetStmt(&'hir LetStmt<'hir>), @@ -4200,6 +4224,7 @@ impl<'hir> Node<'hir> { | Node::Block(..) | Node::Ctor(..) | Node::Pat(..) + | Node::PatExpr(..) | Node::Arm(..) | Node::LetStmt(..) | Node::Crate(..) diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index f0480afd139f4..ef863aca09052 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -342,6 +342,9 @@ pub trait Visitor<'v>: Sized { fn visit_pat_field(&mut self, f: &'v PatField<'v>) -> Self::Result { walk_pat_field(self, f) } + fn visit_pat_expr(&mut self, expr: &'v PatExpr<'v>) -> Self::Result { + walk_pat_expr(self, expr) + } fn visit_anon_const(&mut self, c: &'v AnonConst) -> Self::Result { walk_anon_const(self, c) } @@ -685,10 +688,10 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat<'v>) -> V: try_visit!(visitor.visit_ident(ident)); visit_opt!(visitor, visit_pat, optional_subpattern); } - PatKind::Lit(ref expression) => try_visit!(visitor.visit_expr(expression)), + PatKind::Expr(ref expression) => try_visit!(visitor.visit_pat_expr(expression)), PatKind::Range(ref lower_bound, ref upper_bound, _) => { - visit_opt!(visitor, visit_expr, lower_bound); - visit_opt!(visitor, visit_expr, upper_bound); + visit_opt!(visitor, visit_pat_expr, lower_bound); + visit_opt!(visitor, visit_pat_expr, upper_bound); } PatKind::Never | PatKind::Wild | PatKind::Err(_) => (), PatKind::Slice(prepatterns, ref slice_pattern, postpatterns) => { @@ -710,6 +713,15 @@ pub fn walk_pat_field<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v PatField<' visitor.visit_pat(field.pat) } +pub fn walk_pat_expr<'v, V: Visitor<'v>>(visitor: &mut V, expr: &'v PatExpr<'v>) -> V::Result { + try_visit!(visitor.visit_id(expr.hir_id)); + match &expr.kind { + PatExprKind::Lit { .. } => V::Result::output(), + PatExprKind::ConstBlock(c) => visitor.visit_inline_const(c), + PatExprKind::Path(qpath) => visitor.visit_qpath(qpath, expr.hir_id, expr.span), + } +} + pub fn walk_anon_const<'v, V: Visitor<'v>>(visitor: &mut V, constant: &'v AnonConst) -> V::Result { try_visit!(visitor.visit_id(constant.hir_id)); visitor.visit_nested_body(constant.body) diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index ffc0657eebf1d..e5f98bdfb7fed 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -704,7 +704,7 @@ fn resolve_local<'tcx>( | PatKind::Wild | PatKind::Never | PatKind::Path(_) - | PatKind::Lit(_) + | PatKind::Expr(_) | PatKind::Range(_, _, _) | PatKind::Err(_) => false, } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 2154568c51267..0a41dad0dd837 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -2449,17 +2449,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { Ty::new_error(tcx, err) } hir::PatKind::Range(start, end, include_end) => { - let expr_to_const = |expr: &'tcx hir::Expr<'tcx>| -> ty::Const<'tcx> { - let (expr, neg) = match expr.kind { - hir::ExprKind::Unary(hir::UnOp::Neg, negated) => { - (negated, Some((expr.hir_id, expr.span))) - } - _ => (expr, None), - }; - let (c, c_ty) = match &expr.kind { - hir::ExprKind::Lit(lit) => { + let expr_to_const = |expr: &'tcx hir::PatExpr<'tcx>| -> ty::Const<'tcx> { + let (c, c_ty) = match expr.kind { + hir::PatExprKind::Lit { lit, negated } => { let lit_input = - LitToConstInput { lit: &lit.node, ty, neg: neg.is_some() }; + LitToConstInput { lit: &lit.node, ty, neg: negated }; let ct = match tcx.lit_to_const(lit_input) { Ok(c) => c, Err(LitToConstError::Reported(err)) => { @@ -2470,23 +2464,30 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { (ct, ty) } - hir::ExprKind::Path(hir::QPath::Resolved( + hir::PatExprKind::Path(hir::QPath::Resolved( _, path @ &hir::Path { res: Res::Def(DefKind::ConstParam, def_id), .. }, )) => { - let _ = self.prohibit_generic_args( + match self.prohibit_generic_args( path.segments.iter(), GenericsArgsErrExtend::Param(def_id), - ); - let ty = tcx - .type_of(def_id) - .no_bound_vars() - .expect("const parameter types cannot be generic"); - let ct = self.lower_const_param(def_id, expr.hir_id); - (ct, ty) + ) { + Ok(()) => { + let ty = tcx + .type_of(def_id) + .no_bound_vars() + .expect("const parameter types cannot be generic"); + let ct = self.lower_const_param(def_id, expr.hir_id); + (ct, ty) + } + Err(guar) => ( + ty::Const::new_error(tcx, guar), + Ty::new_error(tcx, guar), + ), + } } _ => { @@ -2497,9 +2498,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } }; self.record_ty(expr.hir_id, c_ty, expr.span); - if let Some((id, span)) = neg { - self.record_ty(id, c_ty, span); - } c }; diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 16bb0dd328cdc..39b6823cf0e0c 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -199,6 +199,7 @@ impl<'a> State<'a> { Node::OpaqueTy(o) => self.print_opaque_ty(o), Node::Pat(a) => self.print_pat(a), Node::PatField(a) => self.print_patfield(a), + Node::PatExpr(a) => self.print_pat_expr(a), Node::Arm(a) => self.print_arm(a), Node::Infer(_) => self.word("_"), Node::PreciseCapturingNonLifetimeArg(param) => self.print_ident(param.ident), @@ -1849,6 +1850,19 @@ impl<'a> State<'a> { } } + fn print_pat_expr(&mut self, expr: &hir::PatExpr<'_>) { + match &expr.kind { + hir::PatExprKind::Lit { lit, negated } => { + if *negated { + self.word("-"); + } + self.print_literal(lit); + } + hir::PatExprKind::ConstBlock(c) => self.print_inline_const(c), + hir::PatExprKind::Path(qpath) => self.print_qpath(qpath, true), + } + } + fn print_pat(&mut self, pat: &hir::Pat<'_>) { self.maybe_print_comment(pat.span.lo()); self.ann.pre(self, AnnNode::Pat(pat)); @@ -1966,17 +1980,17 @@ impl<'a> State<'a> { self.pclose(); } } - PatKind::Lit(e) => self.print_expr(e), + PatKind::Expr(e) => self.print_pat_expr(e), PatKind::Range(begin, end, end_kind) => { if let Some(expr) = begin { - self.print_expr(expr); + self.print_pat_expr(expr); } match end_kind { RangeEnd::Included => self.word("..."), RangeEnd::Excluded => self.word(".."), } if let Some(expr) = end { - self.print_expr(expr); + self.print_pat_expr(expr); } } PatKind::Slice(before, slice, after) => { diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 8c8a8d6d9228a..3bb518e7f9711 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -430,6 +430,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | hir::Node::AssocItemConstraint(_) | hir::Node::TraitRef(_) | hir::Node::PatField(_) + | hir::Node::PatExpr(_) | hir::Node::LetStmt(_) | hir::Node::Synthetic | hir::Node::Err(_) @@ -484,7 +485,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | hir::PatKind::Box(_) | hir::PatKind::Ref(_, _) | hir::PatKind::Deref(_) - | hir::PatKind::Lit(_) + | hir::PatKind::Expr(_) | hir::PatKind::Range(_, _, _) | hir::PatKind::Slice(_, _, _) | hir::PatKind::Err(_) => true, @@ -837,7 +838,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // We always require that the type provided as the value for // a type parameter outlives the moment of instantiation. let args = self.typeck_results.borrow().node_args(expr.hir_id); - self.add_wf_bounds(args, expr); + self.add_wf_bounds(args, expr.span); ty } @@ -1796,7 +1797,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - fn check_expr_const_block( + pub(super) fn check_expr_const_block( &self, block: &'tcx hir::ConstBlock, expected: Expectation<'tcx>, diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index ad764e5563b94..1f48b703e4ac8 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -595,7 +595,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx let place_ty = place.place.ty(); needs_to_be_read |= self.is_multivariant_adt(place_ty, pat.span); } - PatKind::Lit(_) | PatKind::Range(..) => { + PatKind::Expr(_) | PatKind::Range(..) => { // If the PatKind is a Lit or a Range then we want // to borrow discr. needs_to_be_read = true; @@ -1803,7 +1803,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx PatKind::Path(_) | PatKind::Binding(.., None) - | PatKind::Lit(..) + | PatKind::Expr(..) | PatKind::Range(..) | PatKind::Never | PatKind::Wild diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 2f6e50c80149e..4130f0c11dd78 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -577,11 +577,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } /// Registers obligations that all `args` are well-formed. - pub(crate) fn add_wf_bounds(&self, args: GenericArgsRef<'tcx>, expr: &hir::Expr<'_>) { + pub(crate) fn add_wf_bounds(&self, args: GenericArgsRef<'tcx>, span: Span) { for arg in args.iter().filter(|arg| { matches!(arg.unpack(), GenericArgKind::Type(..) | GenericArgKind::Const(..)) }) { - self.register_wf_obligation(arg, expr.span, ObligationCauseCode::WellFormed(None)); + self.register_wf_obligation(arg, span, ObligationCauseCode::WellFormed(None)); } } @@ -1039,6 +1039,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { def_id, span, ), + Res::Err => { + return ( + Ty::new_error( + tcx, + tcx.dcx().span_delayed_bug(span, "could not resolve path {:?}"), + ), + res, + ); + } _ => bug!("instantiate_value_path on {:?}", res), }; diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index 0c93c9817b467..f549ced9dc332 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -611,7 +611,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { // this is a projection from a trait reference, so we have to // make sure that the trait reference inputs are well-formed. - self.add_wf_bounds(all_args, self.call_expr); + self.add_wf_bounds(all_args, self.call_expr.span); // the function type must also be well-formed (this is not // implied by the args being well-formed because of inherent diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index b4f1dcfb9cc8a..72a1e4af9bfce 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -170,6 +170,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span, .. }) + | hir::Node::PatExpr(&hir::PatExpr { + kind: hir::PatExprKind::Path(QPath::TypeRelative(rcvr, segment)), + span, + .. + }) | hir::Node::Pat(&hir::Pat { kind: hir::PatKind::Path(QPath::TypeRelative(rcvr, segment)) diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 4870e6193c3f1..36094657eafd1 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -30,6 +30,7 @@ use tracing::{debug, instrument, trace}; use ty::VariantDef; use super::report_unexpected_variant_res; +use crate::expectation::Expectation; use crate::gather_locals::DeclOrigin; use crate::{FnCtxt, LoweredTy, errors}; @@ -270,7 +271,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { PatKind::Wild | PatKind::Err(_) => expected, // We allow any type here; we ensure that the type is uninhabited during match checking. PatKind::Never => expected, - PatKind::Lit(lt) => self.check_pat_lit(pat.span, lt, expected, ti), + PatKind::Expr(lt) => self.check_pat_lit(pat.span, lt, expected, ti), PatKind::Range(lhs, rhs, _) => self.check_pat_range(pat.span, lhs, rhs, expected, ti), PatKind::Binding(ba, var_id, ident, sub) => { self.check_pat_ident(pat, ba, var_id, ident, sub, expected, pat_info) @@ -279,7 +280,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.check_pat_tuple_struct(pat, qpath, subpats, ddpos, expected, pat_info) } PatKind::Path(ref qpath) => { - self.check_pat_path(pat, qpath, path_res.unwrap(), expected, ti) + self.check_pat_path(pat.hir_id, pat.span, qpath, path_res.unwrap(), expected, ti) } PatKind::Struct(ref qpath, fields, has_rest_pat) => { self.check_pat_struct(pat, qpath, fields, has_rest_pat, expected, pat_info) @@ -398,7 +399,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // As a result, we allow `if let 0 = &&0 {}` but not `if let "foo" = &&"foo" {}`. // // Call `resolve_vars_if_possible` here for inline const blocks. - PatKind::Lit(lt) => match self.resolve_vars_if_possible(self.check_expr(lt)).kind() { + PatKind::Expr(lt) => match self.resolve_vars_if_possible(self.check_pat_expr_unadjusted(lt)).kind() { ty::Ref(..) => AdjustMode::Pass, _ => AdjustMode::Peel, }, @@ -493,10 +494,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (expected, def_br, max_ref_mutbl) } + fn check_pat_expr_unadjusted(&self, lt: &'tcx hir::PatExpr<'tcx>) -> Ty<'tcx> { + let ty = match <.kind { + rustc_hir::PatExprKind::Lit { lit, .. } => { + self.check_expr_lit(lit, Expectation::NoExpectation) + } + rustc_hir::PatExprKind::ConstBlock(c) => { + self.check_expr_const_block(c, Expectation::NoExpectation) + } + rustc_hir::PatExprKind::Path(qpath) => { + let (res, opt_ty, segments) = + self.resolve_ty_and_res_fully_qualified_call(qpath, lt.hir_id, lt.span); + self.instantiate_value_path(segments, opt_ty, res, lt.span, lt.span, lt.hir_id).0 + } + }; + self.write_ty(lt.hir_id, ty); + ty + } + fn check_pat_lit( &self, span: Span, - lt: &hir::Expr<'tcx>, + lt: &hir::PatExpr<'tcx>, expected: Ty<'tcx>, ti: &TopInfo<'tcx>, ) -> Ty<'tcx> { @@ -507,7 +526,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Byte string patterns behave the same way as array patterns // They can denote both statically and dynamically-sized byte arrays. let mut pat_ty = ty; - if let hir::ExprKind::Lit(Spanned { node: ast::LitKind::ByteStr(..), .. }) = lt.kind { + if let hir::PatExprKind::Lit { + lit: Spanned { node: ast::LitKind::ByteStr(..), .. }, .. + } = lt.kind + { let expected = self.structurally_resolve_type(span, expected); if let ty::Ref(_, inner_ty, _) = *expected.kind() && self.try_structurally_resolve_type(span, inner_ty).is_slice() @@ -524,7 +546,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } if self.tcx.features().string_deref_patterns() - && let hir::ExprKind::Lit(Spanned { node: ast::LitKind::Str(..), .. }) = lt.kind + && let hir::PatExprKind::Lit { + lit: Spanned { node: ast::LitKind::Str(..), .. }, .. + } = lt.kind { let tcx = self.tcx; let expected = self.resolve_vars_if_possible(expected); @@ -565,15 +589,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn check_pat_range( &self, span: Span, - lhs: Option<&'tcx hir::Expr<'tcx>>, - rhs: Option<&'tcx hir::Expr<'tcx>>, + lhs: Option<&'tcx hir::PatExpr<'tcx>>, + rhs: Option<&'tcx hir::PatExpr<'tcx>>, expected: Ty<'tcx>, ti: &TopInfo<'tcx>, ) -> Ty<'tcx> { - let calc_side = |opt_expr: Option<&'tcx hir::Expr<'tcx>>| match opt_expr { + let calc_side = |opt_expr: Option<&'tcx hir::PatExpr<'tcx>>| match opt_expr { None => None, Some(expr) => { - let ty = self.check_expr(expr); + let ty = self.check_pat_expr_unadjusted(expr); // Check that the end-point is possibly of numeric or char type. // The early check here is not for correctness, but rather better // diagnostics (e.g. when `&str` is being matched, `expected` will @@ -919,7 +943,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | PatKind::Box(..) | PatKind::Deref(_) | PatKind::Ref(..) - | PatKind::Lit(..) + | PatKind::Expr(..) | PatKind::Range(..) | PatKind::Err(_) => break 'block None, }, @@ -1053,7 +1077,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn check_pat_path( &self, - pat: &Pat<'tcx>, + hir_id: HirId, + span: Span, qpath: &hir::QPath<'_>, path_resolution: (Res, Option>, &'tcx [hir::PathSegment<'tcx>]), expected: Ty<'tcx>, @@ -1072,8 +1097,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } Res::Def(DefKind::AssocFn | DefKind::Ctor(_, CtorKind::Fn) | DefKind::Variant, _) => { let expected = "unit struct, unit variant or constant"; - let e = - report_unexpected_variant_res(tcx, res, None, qpath, pat.span, E0533, expected); + let e = report_unexpected_variant_res(tcx, res, None, qpath, span, E0533, expected); return Ty::new_error(tcx, e); } Res::SelfCtor(def_id) => { @@ -1088,7 +1112,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { res, None, qpath, - pat.span, + span, E0533, "unit struct", ); @@ -1107,11 +1131,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Type-check the path. let (pat_ty, pat_res) = - self.instantiate_value_path(segments, opt_ty, res, pat.span, pat.span, pat.hir_id); + self.instantiate_value_path(segments, opt_ty, res, span, span, hir_id); if let Err(err) = - self.demand_suptype_with_origin(&self.pattern_cause(ti, pat.span), expected, pat_ty) + self.demand_suptype_with_origin(&self.pattern_cause(ti, span), expected, pat_ty) { - self.emit_bad_pat_path(err, pat, res, pat_res, pat_ty, segments); + self.emit_bad_pat_path(err, hir_id, span, res, pat_res, pat_ty, segments); } pat_ty } @@ -1154,13 +1178,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn emit_bad_pat_path( &self, mut e: Diag<'_>, - pat: &hir::Pat<'tcx>, + hir_id: HirId, + pat_span: Span, res: Res, pat_res: Res, pat_ty: Ty<'tcx>, segments: &'tcx [hir::PathSegment<'tcx>], ) { - let pat_span = pat.span; if let Some(span) = self.tcx.hir().res_span(pat_res) { e.span_label(span, format!("{} defined here", res.descr())); if let [hir::PathSegment { ident, .. }] = &*segments { @@ -1173,7 +1197,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { res.descr(), ), ); - match self.tcx.parent_hir_node(pat.hir_id) { + match self.tcx.parent_hir_node(hir_id) { hir::Node::PatField(..) => { e.span_suggestion_verbose( ident.span.shrink_to_hi(), @@ -1813,9 +1837,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } else if inexistent_fields.len() == 1 { match pat_field.pat.kind { - PatKind::Lit(expr) + PatKind::Expr(_) if !self.may_coerce( - self.typeck_results.borrow().expr_ty(expr), + self.typeck_results.borrow().node_type(pat_field.pat.hir_id), self.field_ty(field.span, field_def, args), ) => {} _ => { diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index 53993ba8d6ca4..cac891c4e4c4f 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -147,15 +147,16 @@ impl<'a, 'tcx> Visitor<'tcx> for InferBorrowKindVisitor<'a, 'tcx> { self.visit_body(body); self.fcx.analyze_closure(expr.hir_id, expr.span, body_id, body, capture_clause); } - hir::ExprKind::ConstBlock(anon_const) => { - let body = self.fcx.tcx.hir().body(anon_const.body); - self.visit_body(body); - } _ => {} } intravisit::walk_expr(self, expr); } + + fn visit_inline_const(&mut self, c: &'tcx hir::ConstBlock) { + let body = self.fcx.tcx.hir().body(c.body); + self.visit_body(body); + } } impl<'a, 'tcx> FnCtxt<'a, 'tcx> { diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index 5612aa75aae44..f63a0b17964f7 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -246,6 +246,13 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { } } } + + fn visit_const_block(&mut self, span: Span, anon_const: &hir::ConstBlock) { + self.visit_node_id(span, anon_const.hir_id); + + let body = self.tcx().hir().body(anon_const.body); + self.visit_body(body); + } } /////////////////////////////////////////////////////////////////////////// @@ -275,11 +282,8 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> { hir::ExprKind::Field(..) | hir::ExprKind::OffsetOf(..) => { self.visit_field_id(e.hir_id); } - hir::ExprKind::ConstBlock(anon_const) => { - self.visit_node_id(e.span, anon_const.hir_id); - - let body = self.tcx().hir().body(anon_const.body); - self.visit_body(body); + hir::ExprKind::ConstBlock(ref anon_const) => { + self.visit_const_block(e.span, anon_const); } _ => {} } @@ -335,6 +339,14 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> { intravisit::walk_pat(self, p); } + fn visit_pat_expr(&mut self, expr: &'tcx hir::PatExpr<'tcx>) { + self.visit_node_id(expr.span, expr.hir_id); + if let hir::PatExprKind::ConstBlock(c) = &expr.kind { + self.visit_const_block(expr.span, c); + } + intravisit::walk_pat_expr(self, expr); + } + fn visit_local(&mut self, l: &'tcx hir::LetStmt<'tcx>) { intravisit::walk_local(self, l); let var_ty = self.fcx.local_ty(l.span, l.hir_id); diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 8b1526bc747d4..3059adb3fda10 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -1220,7 +1220,7 @@ impl EarlyLintPass for UnusedParens { // Do not lint on `(..)` as that will result in the other arms being useless. Paren(_) // The other cases do not contain sub-patterns. - | Wild | Never | Rest | Lit(..) | MacCall(..) | Range(..) | Ident(.., None) | Path(..) | Err(_) => {}, + | Wild | Never | Rest | Expr(..) | MacCall(..) | Range(..) | Ident(.., None) | Path(..) | Err(_) => {}, // These are list-like patterns; parens can always be removed. TupleStruct(_, _, ps) | Tuple(ps) | Slice(ps) | Or(ps) => for p in ps { self.check_unused_parens_pat(cx, p, false, false, keep_space); diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index dee4c424387f6..632935eefeb66 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -938,6 +938,7 @@ impl<'hir> Map<'hir> { Node::OpaqueTy(op) => op.span, Node::Pat(pat) => pat.span, Node::PatField(field) => field.span, + Node::PatExpr(lit) => lit.span, Node::Arm(arm) => arm.span, Node::Block(block) => block.span, Node::Ctor(..) => self.span_with_body(self.tcx.parent_hir_id(hir_id)), @@ -1209,6 +1210,7 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String { Node::OpaqueTy(_) => node_str("opaque type"), Node::Pat(_) => node_str("pat"), Node::PatField(_) => node_str("pattern field"), + Node::PatExpr(_) => node_str("pattern literal"), Node::Param(_) => node_str("param"), Node::Arm(_) => node_str("arm"), Node::Block(_) => node_str("block"), diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 54510faf2e182..242b62dfa8dde 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -154,7 +154,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { fn lower_pattern_range_endpoint( &mut self, - expr: Option<&'tcx hir::Expr<'tcx>>, + expr: Option<&'tcx hir::PatExpr<'tcx>>, ) -> Result< (Option>, Option>, Option), ErrorGuaranteed, @@ -200,13 +200,12 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { /// This is only called when the range is already known to be malformed. fn error_on_literal_overflow( &self, - expr: Option<&'tcx hir::Expr<'tcx>>, + expr: Option<&'tcx hir::PatExpr<'tcx>>, ty: Ty<'tcx>, ) -> Result<(), ErrorGuaranteed> { - use hir::{ExprKind, UnOp}; use rustc_ast::ast::LitKind; - let Some(mut expr) = expr else { + let Some(expr) = expr else { return Ok(()); }; let span = expr.span; @@ -214,12 +213,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { // We need to inspect the original expression, because if we only inspect the output of // `eval_bits`, an overflowed value has already been wrapped around. // We mostly copy the logic from the `rustc_lint::OVERFLOWING_LITERALS` lint. - let mut negated = false; - if let ExprKind::Unary(UnOp::Neg, sub_expr) = expr.kind { - negated = true; - expr = sub_expr; - } - let ExprKind::Lit(lit) = expr.kind else { + let hir::PatExprKind::Lit { lit, negated } = expr.kind else { return Ok(()); }; let LitKind::Int(lit_val, _) = lit.node else { @@ -248,8 +242,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { fn lower_pattern_range( &mut self, - lo_expr: Option<&'tcx hir::Expr<'tcx>>, - hi_expr: Option<&'tcx hir::Expr<'tcx>>, + lo_expr: Option<&'tcx hir::PatExpr<'tcx>>, + hi_expr: Option<&'tcx hir::PatExpr<'tcx>>, end: RangeEnd, ty: Ty<'tcx>, span: Span, @@ -330,7 +324,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { hir::PatKind::Never => PatKind::Never, - hir::PatKind::Lit(value) => self.lower_lit(value), + hir::PatKind::Expr(value) => self.lower_lit(value), hir::PatKind::Range(ref lo_expr, ref hi_expr, end) => { let (lo_expr, hi_expr) = (lo_expr.as_deref(), hi_expr.as_deref()); @@ -662,25 +656,18 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { /// 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> { - let (lit, neg) = match expr.kind { - hir::ExprKind::Path(ref qpath) => { + fn lower_lit(&mut self, expr: &'tcx hir::PatExpr<'tcx>) -> PatKind<'tcx> { + let (lit, neg) = match &expr.kind { + hir::PatExprKind::Path(qpath) => { return self.lower_path(qpath, expr.hir_id, expr.span).kind; } - hir::ExprKind::ConstBlock(ref anon_const) => { + hir::PatExprKind::ConstBlock(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 hir::ExprKind::Lit(ref lit) = expr.kind else { - span_bug!(expr.span, "not a literal: {:?}", expr); - }; - (lit, true) - } - _ => span_bug!(expr.span, "not a literal: {:?}", expr), + hir::PatExprKind::Lit { lit, negated } => (lit, *negated), }; - let ct_ty = self.typeck_results.expr_ty(expr); + let ct_ty = self.typeck_results.node_type(expr.hir_id); let lit_input = LitToConstInput { lit: &lit.node, ty: ct_ty, neg }; match self.tcx.at(expr.span).lit_to_const(lit_input) { Ok(constant) => self.const_to_pat(constant, ct_ty, expr.hir_id, lit.span).kind, diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 5ad3da2196f8f..64bcb1a5a36cc 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -656,14 +656,14 @@ impl<'a> Parser<'a> { fn visit_pat(&mut self, p: &'a Pat) -> Self::Result { match &p.kind { // Base expression - PatKind::Err(_) | PatKind::Lit(_) => { + PatKind::Err(_) | PatKind::Expr(_) => { self.maybe_add_suggestions_then_emit(p.span, p.span, false) } // Sub-patterns // FIXME: this doesn't work with recursive subpats (`&mut &mut `) PatKind::Box(subpat) | PatKind::Ref(subpat, _) - if matches!(subpat.kind, PatKind::Err(_) | PatKind::Lit(_)) => + if matches!(subpat.kind, PatKind::Err(_) | PatKind::Expr(_)) => { self.maybe_add_suggestions_then_emit(subpat.span, p.span, false) } @@ -766,7 +766,7 @@ impl<'a> Parser<'a> { if let Some(re) = self.parse_range_end() { self.parse_pat_range_begin_with(const_expr, re)? } else { - PatKind::Lit(const_expr) + PatKind::Expr(const_expr) } } else if self.is_builtin() { self.parse_pat_builtin()? @@ -833,7 +833,7 @@ impl<'a> Parser<'a> { .struct_span_err(self_.token.span, msg) .with_span_label(self_.token.span, format!("expected {expected}")) }); - PatKind::Lit(self.mk_expr(lo, ExprKind::Lit(lit))) + PatKind::Expr(self.mk_expr(lo, ExprKind::Lit(lit))) } else { // Try to parse everything else as literal with optional minus match self.parse_literal_maybe_minus() { @@ -845,7 +845,7 @@ impl<'a> Parser<'a> { match self.parse_range_end() { Some(form) => self.parse_pat_range_begin_with(begin, form)?, - None => PatKind::Lit(begin), + None => PatKind::Expr(begin), } } Err(err) => return self.fatal_unexpected_non_pat(err, expected), @@ -989,7 +989,7 @@ impl<'a> Parser<'a> { match &pat.kind { // recover ranges with parentheses around the `(start)..` - PatKind::Lit(begin) + PatKind::Expr(begin) if self.may_recover() && let Some(form) = self.parse_range_end() => { diff --git a/compiler/rustc_passes/src/input_stats.rs b/compiler/rustc_passes/src/input_stats.rs index 88d69eb36788d..6617cf2f723a9 100644 --- a/compiler/rustc_passes/src/input_stats.rs +++ b/compiler/rustc_passes/src/input_stats.rs @@ -304,7 +304,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { Box, Deref, Ref, - Lit, + Expr, Guard, Range, Slice, @@ -587,7 +587,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { Box, Deref, Ref, - Lit, + Expr, Range, Slice, Rest, diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 6ee02e9f47f15..d15eca6927010 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1130,7 +1130,9 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { let None = following_seg else { return }; for rib in self.ribs[ValueNS].iter().rev() { for (def_id, spans) in &rib.patterns_with_skipped_bindings { - if let Some(fields) = self.r.field_idents(*def_id) { + if let DefKind::Struct | DefKind::Variant = self.r.tcx.def_kind(*def_id) + && let Some(fields) = self.r.field_idents(*def_id) + { for field in fields { if field.name == segment.ident.name { if spans.iter().all(|(_, had_error)| had_error.is_err()) { diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index 8bfa9cc94b341..aa664998f979e 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -1592,15 +1592,9 @@ impl Step for Extended { prepare("cargo"); prepare("rust-std"); prepare("rust-analysis"); - - for tool in &[ - "clippy", - "rustfmt", - "rust-analyzer", - "rust-docs", - "miri", - "rustc-codegen-cranelift", - ] { + prepare("clippy"); + prepare("rust-analyzer"); + for tool in &["rust-docs", "miri", "rustc-codegen-cranelift"] { if built_tools.contains(tool) { prepare(tool); } @@ -1640,8 +1634,6 @@ impl Step for Extended { "rust-analyzer-preview".to_string() } else if name == "clippy" { "clippy-preview".to_string() - } else if name == "rustfmt" { - "rustfmt-preview".to_string() } else if name == "miri" { "miri-preview".to_string() } else if name == "rustc-codegen-cranelift" { @@ -1661,7 +1653,7 @@ impl Step for Extended { prepare("cargo"); prepare("rust-analysis"); prepare("rust-std"); - for tool in &["clippy", "rustfmt", "rust-analyzer", "rust-docs", "miri"] { + for tool in &["clippy", "rust-analyzer", "rust-docs", "miri"] { if built_tools.contains(tool) { prepare(tool); } @@ -1779,24 +1771,6 @@ impl Step for Extended { .arg(etc.join("msi/remove-duplicates.xsl")) .run(builder); } - if built_tools.contains("rustfmt") { - command(&heat) - .current_dir(&exe) - .arg("dir") - .arg("rustfmt") - .args(heat_flags) - .arg("-cg") - .arg("RustFmtGroup") - .arg("-dr") - .arg("RustFmt") - .arg("-var") - .arg("var.RustFmtDir") - .arg("-out") - .arg(exe.join("RustFmtGroup.wxs")) - .arg("-t") - .arg(etc.join("msi/remove-duplicates.xsl")) - .run(builder); - } if built_tools.contains("miri") { command(&heat) .current_dir(&exe) @@ -1868,9 +1842,6 @@ impl Step for Extended { if built_tools.contains("clippy") { cmd.arg("-dClippyDir=clippy"); } - if built_tools.contains("rustfmt") { - cmd.arg("-dRustFmtDir=rustfmt"); - } if built_tools.contains("rust-docs") { cmd.arg("-dDocsDir=rust-docs"); } @@ -1897,9 +1868,6 @@ impl Step for Extended { if built_tools.contains("clippy") { candle("ClippyGroup.wxs".as_ref()); } - if built_tools.contains("rustfmt") { - candle("RustFmtGroup.wxs".as_ref()); - } if built_tools.contains("miri") { candle("MiriGroup.wxs".as_ref()); } @@ -1938,9 +1906,6 @@ impl Step for Extended { if built_tools.contains("clippy") { cmd.arg("ClippyGroup.wixobj"); } - if built_tools.contains("rustfmt") { - cmd.arg("RustFmtGroup.wixobj"); - } if built_tools.contains("miri") { cmd.arg("MiriGroup.wixobj"); } diff --git a/src/etc/installer/msi/rust.wxs b/src/etc/installer/msi/rust.wxs index 2d155bf0b1019..f29e1e4d27a27 100644 --- a/src/etc/installer/msi/rust.wxs +++ b/src/etc/installer/msi/rust.wxs @@ -172,11 +172,6 @@ - - - - - @@ -284,41 +279,7 @@ - - - - - - - - - - - - - - - + diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 1fb35750c15f5..99e88f878fba6 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -314,9 +314,9 @@ pub(crate) fn name_from_pat(p: &hir::Pat<'_>) -> Symbol { PatKind::Box(p) => return name_from_pat(p), PatKind::Deref(p) => format!("deref!({})", name_from_pat(p)), PatKind::Ref(p, _) => return name_from_pat(p), - PatKind::Lit(..) => { + PatKind::Expr(..) => { warn!( - "tried to get argument name from PatKind::Lit, which is silly in function arguments" + "tried to get argument name from PatKind::Expr, which is silly in function arguments" ); return Symbol::intern("()"); } diff --git a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs index 3b3a78cb11530..c04a73c890f0e 100644 --- a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs +++ b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs @@ -3,8 +3,11 @@ use clippy_utils::numeric_literal; use clippy_utils::source::snippet_opt; use rustc_ast::ast::{LitFloatType, LitIntType, LitKind}; use rustc_errors::Applicability; -use rustc_hir::intravisit::{Visitor, walk_expr, walk_stmt}; -use rustc_hir::{Block, Body, ConstContext, Expr, ExprKind, FnRetTy, HirId, Lit, Stmt, StmtKind, StructTailExpr}; +use rustc_hir::intravisit::{Visitor, walk_expr, walk_pat, walk_stmt}; +use rustc_hir::{ + Block, Body, ConstContext, Expr, ExprKind, FnRetTy, HirId, Lit, Pat, PatExpr, PatExprKind, PatKind, Stmt, StmtKind, + StructTailExpr, +}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::{self, FloatTy, IntTy, PolyFnSig, Ty}; @@ -219,6 +222,22 @@ impl<'tcx> Visitor<'tcx> for NumericFallbackVisitor<'_, 'tcx> { walk_expr(self, expr); } + fn visit_pat(&mut self, pat: &'tcx Pat<'_>) { + match pat.kind { + PatKind::Expr(&PatExpr { + hir_id, + kind: PatExprKind::Lit { lit, .. }, + .. + }) => { + let ty = self.cx.typeck_results().node_type(hir_id); + self.check_lit(lit, ty, hir_id); + return; + }, + _ => {}, + } + walk_pat(self, pat) + } + fn visit_stmt(&mut self, stmt: &'tcx Stmt<'_>) { match stmt.kind { // we cannot check the exact type since it's a hir::Ty which does not implement `is_numeric` diff --git a/src/tools/clippy/clippy_lints/src/equatable_if_let.rs b/src/tools/clippy/clippy_lints/src/equatable_if_let.rs index 9c8edfd6113f6..8a5cf7f56d5f6 100644 --- a/src/tools/clippy/clippy_lints/src/equatable_if_let.rs +++ b/src/tools/clippy/clippy_lints/src/equatable_if_let.rs @@ -56,7 +56,7 @@ fn unary_pattern(pat: &Pat<'_>) -> bool { PatKind::Struct(_, a, etc) => !etc && a.iter().all(|x| unary_pattern(x.pat)), PatKind::Tuple(a, etc) | PatKind::TupleStruct(_, a, etc) => etc.as_opt_usize().is_none() && array_rec(a), PatKind::Ref(x, _) | PatKind::Box(x) | PatKind::Deref(x) | PatKind::Guard(x, _) => unary_pattern(x), - PatKind::Path(_) | PatKind::Lit(_) => true, + PatKind::Path(_) | PatKind::Expr(_) => true, } } diff --git a/src/tools/clippy/clippy_lints/src/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs index 3ea758e176f0b..1c63ca9d97435 100644 --- a/src/tools/clippy/clippy_lints/src/len_zero.rs +++ b/src/tools/clippy/clippy_lints/src/len_zero.rs @@ -8,8 +8,8 @@ use rustc_hir::def::Res; use rustc_hir::def_id::{DefId, DefIdSet}; use rustc_hir::{ AssocItemKind, BinOpKind, Expr, ExprKind, FnRetTy, GenericArg, GenericBound, ImplItem, ImplItemKind, - ImplicitSelfKind, Item, ItemKind, Mutability, Node, OpaqueTyOrigin, PatKind, PathSegment, PrimTy, QPath, - TraitItemRef, TyKind, + ImplicitSelfKind, Item, ItemKind, Mutability, Node, OpaqueTyOrigin, PatExprKind, PatKind, PathSegment, PrimTy, + QPath, TraitItemRef, TyKind, }; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{self, AssocKind, FnSig, Ty}; @@ -163,7 +163,13 @@ impl<'tcx> LateLintPass<'tcx> for LenZero { if let ExprKind::Let(lt) = expr.kind && match lt.pat.kind { PatKind::Slice([], None, []) => true, - PatKind::Lit(lit) if is_empty_string(lit) => true, + PatKind::Expr(lit) => match lit.kind { + PatExprKind::Lit { lit, .. } => match lit.node { + LitKind::Str(lit, _) => lit.as_str().is_empty(), + _ => false, + }, + _ => false, + }, _ => false, } && !expr.span.from_expansion() diff --git a/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs b/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs index 3f01f3cf30aea..5b9eedd9b8bf1 100644 --- a/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs +++ b/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs @@ -7,7 +7,7 @@ use clippy_utils::{higher, is_in_const_context, path_to_local, peel_ref_operator use rustc_ast::LitKind::{Byte, Char}; use rustc_ast::ast::RangeLimits; use rustc_errors::Applicability; -use rustc_hir::{Expr, ExprKind, Node, Param, PatKind, RangeEnd}; +use rustc_hir::{Expr, ExprKind, Node, Param, PatKind, RangeEnd, PatExpr, PatExprKind, Lit}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; use rustc_session::impl_lint_pass; @@ -115,7 +115,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualIsAsciiCheck { { let arg = peel_ref_operators(cx, arg); let ty_sugg = get_ty_sugg(cx, arg, start); - let range = check_range(start, end); + let range = check_expr_range(start, end); check_is_ascii(cx, expr.span, arg, &range, ty_sugg); } } @@ -196,19 +196,34 @@ fn check_pat(pat_kind: &PatKind<'_>) -> CharRange { } } -fn check_range(start: &Expr<'_>, end: &Expr<'_>) -> CharRange { +fn check_expr_range(start: &Expr<'_>, end: &Expr<'_>) -> CharRange { if let ExprKind::Lit(start_lit) = &start.kind && let ExprKind::Lit(end_lit) = &end.kind { - match (&start_lit.node, &end_lit.node) { - (Char('a'), Char('z')) | (Byte(b'a'), Byte(b'z')) => CharRange::LowerChar, - (Char('A'), Char('Z')) | (Byte(b'A'), Byte(b'Z')) => CharRange::UpperChar, - (Char('a'), Char('f')) | (Byte(b'a'), Byte(b'f')) => CharRange::LowerHexLetter, - (Char('A'), Char('F')) | (Byte(b'A'), Byte(b'F')) => CharRange::UpperHexLetter, - (Char('0'), Char('9')) | (Byte(b'0'), Byte(b'9')) => CharRange::Digit, - _ => CharRange::Otherwise, - } + check_lit_range(start_lit, end_lit) + } else { + CharRange::Otherwise + } +} + + +fn check_range(start: &PatExpr<'_>, end: &PatExpr<'_>) -> CharRange { + if let PatExprKind::Lit{ lit: start_lit, negated: false } = &start.kind + && let PatExprKind::Lit{ lit: end_lit, negated: false } = &end.kind + { + check_lit_range(start_lit, end_lit) } else { CharRange::Otherwise } } + +fn check_lit_range(start_lit: &Lit, end_lit: &Lit) -> CharRange { + match (&start_lit.node, &end_lit.node) { + (Char('a'), Char('z')) | (Byte(b'a'), Byte(b'z')) => CharRange::LowerChar, + (Char('A'), Char('Z')) | (Byte(b'A'), Byte(b'Z')) => CharRange::UpperChar, + (Char('a'), Char('f')) | (Byte(b'a'), Byte(b'f')) => CharRange::LowerHexLetter, + (Char('A'), Char('F')) | (Byte(b'A'), Byte(b'F')) => CharRange::UpperHexLetter, + (Char('0'), Char('9')) | (Byte(b'0'), Byte(b'9')) => CharRange::Digit, + _ => CharRange::Otherwise, + } +} diff --git a/src/tools/clippy/clippy_lints/src/manual_range_patterns.rs b/src/tools/clippy/clippy_lints/src/manual_range_patterns.rs index ffa3eacf3544f..2e5a92915d9ca 100644 --- a/src/tools/clippy/clippy_lints/src/manual_range_patterns.rs +++ b/src/tools/clippy/clippy_lints/src/manual_range_patterns.rs @@ -3,7 +3,7 @@ use clippy_utils::source::SpanRangeExt; use rustc_ast::LitKind; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; -use rustc_hir::{Expr, ExprKind, PatKind, RangeEnd, UnOp}; +use rustc_hir::{PatExpr, PatExprKind, PatKind, RangeEnd}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_session::declare_lint_pass; @@ -38,14 +38,13 @@ declare_clippy_lint! { } declare_lint_pass!(ManualRangePatterns => [MANUAL_RANGE_PATTERNS]); -fn expr_as_i128(expr: &Expr<'_>) -> Option { - if let ExprKind::Unary(UnOp::Neg, expr) = expr.kind { - expr_as_i128(expr).map(|num| -num) - } else if let ExprKind::Lit(lit) = expr.kind +fn expr_as_i128(expr: &PatExpr<'_>) -> Option { + if let PatExprKind::Lit { lit, negated } = expr.kind && let LitKind::Int(num, _) = lit.node { // Intentionally not handling numbers greater than i128::MAX (for u128 literals) for now. - num.get().try_into().ok() + let n = i128::try_from(num.get()).ok()?; + Some(if negated { -n } else { n }) } else { None } @@ -58,7 +57,7 @@ struct Num { } impl Num { - fn new(expr: &Expr<'_>) -> Option { + fn new(expr: &PatExpr<'_>) -> Option { Some(Self { val: expr_as_i128(expr)?, span: expr.span, @@ -90,7 +89,7 @@ impl LateLintPass<'_> for ManualRangePatterns { let mut ranges_found = Vec::new(); for pat in pats { - if let PatKind::Lit(lit) = pat.kind + if let PatKind::Expr(lit) = pat.kind && let Some(num) = Num::new(lit) { numbers_found.insert(num.val); diff --git a/src/tools/clippy/clippy_lints/src/matches/match_bool.rs b/src/tools/clippy/clippy_lints/src/matches/match_bool.rs index 69105ff0d5c7a..7e43d222a6623 100644 --- a/src/tools/clippy/clippy_lints/src/matches/match_bool.rs +++ b/src/tools/clippy/clippy_lints/src/matches/match_bool.rs @@ -4,7 +4,7 @@ use clippy_utils::source::{expr_block, snippet}; use clippy_utils::sugg::Sugg; use rustc_ast::LitKind; use rustc_errors::Applicability; -use rustc_hir::{Arm, Expr, ExprKind, PatKind}; +use rustc_hir::{Arm, Expr, PatExprKind, PatKind}; use rustc_lint::LateContext; use rustc_middle::ty; @@ -21,8 +21,8 @@ pub(crate) fn check(cx: &LateContext<'_>, scrutinee: &Expr<'_>, arms: &[Arm<'_>] move |diag| { if arms.len() == 2 { // no guards - let exprs = if let PatKind::Lit(arm_bool) = arms[0].pat.kind { - if let ExprKind::Lit(lit) = arm_bool.kind { + let exprs = if let PatKind::Expr(arm_bool) = arms[0].pat.kind { + if let PatExprKind::Lit { lit, .. } = arm_bool.kind { match lit.node { LitKind::Bool(true) => Some((arms[0].body, arms[1].body)), LitKind::Bool(false) => Some((arms[1].body, arms[0].body)), diff --git a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs index 4b731d759723c..28e05c273d5c7 100644 --- a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs +++ b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs @@ -7,7 +7,7 @@ use rustc_arena::DroplessArena; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir::def_id::DefId; -use rustc_hir::{Arm, Expr, ExprKind, HirId, HirIdMap, HirIdMapEntry, HirIdSet, Pat, PatKind, RangeEnd}; +use rustc_hir::{Arm, Expr, HirId, HirIdMap, HirIdMapEntry, HirIdSet, Pat, PatExprKind, PatKind, RangeEnd}; use rustc_lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS; use rustc_lint::{LateContext, LintContext}; use rustc_middle::ty; @@ -311,9 +311,9 @@ impl<'a> NormalizedPat<'a> { ); Self::Tuple(None, pats) }, - PatKind::Lit(e) => match &e.kind { + PatKind::Expr(e) => match &e.kind { // TODO: Handle negative integers. They're currently treated as a wild match. - ExprKind::Lit(lit) => match lit.node { + PatExprKind::Lit { lit, negated: false } => match lit.node { LitKind::Str(sym, _) => Self::LitStr(sym), LitKind::ByteStr(ref bytes, _) | LitKind::CStr(ref bytes, _) => Self::LitBytes(bytes), LitKind::Byte(val) => Self::LitInt(val.into()), @@ -330,7 +330,7 @@ impl<'a> NormalizedPat<'a> { let start = match start { None => 0, Some(e) => match &e.kind { - ExprKind::Lit(lit) => match lit.node { + PatExprKind::Lit { lit, negated: false } => match lit.node { LitKind::Int(val, _) => val.get(), LitKind::Char(val) => val.into(), LitKind::Byte(val) => val.into(), @@ -342,7 +342,7 @@ impl<'a> NormalizedPat<'a> { let (end, bounds) = match end { None => (u128::MAX, RangeEnd::Included), Some(e) => match &e.kind { - ExprKind::Lit(lit) => match lit.node { + PatExprKind::Lit { lit, negated: false } => match lit.node { LitKind::Int(val, _) => (val.get(), bounds), LitKind::Char(val) => (val.into(), bounds), LitKind::Byte(val) => (val.into(), bounds), diff --git a/src/tools/clippy/clippy_lints/src/matches/match_str_case_mismatch.rs b/src/tools/clippy/clippy_lints/src/matches/match_str_case_mismatch.rs index 1267fc9d0a531..9f5b7c855a139 100644 --- a/src/tools/clippy/clippy_lints/src/matches/match_str_case_mismatch.rs +++ b/src/tools/clippy/clippy_lints/src/matches/match_str_case_mismatch.rs @@ -5,7 +5,7 @@ use clippy_utils::ty::is_type_lang_item; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir::intravisit::{Visitor, walk_expr}; -use rustc_hir::{Arm, Expr, ExprKind, LangItem, PatKind}; +use rustc_hir::{Arm, Expr, ExprKind, PatExpr, PatExprKind, LangItem, PatKind}; use rustc_lint::LateContext; use rustc_middle::ty; use rustc_span::Span; @@ -85,8 +85,8 @@ fn verify_case<'a>(case_method: &'a CaseMethod, arms: &'a [Arm<'_>]) -> Option<( }; for arm in arms { - if let PatKind::Lit(Expr { - kind: ExprKind::Lit(lit), + if let PatKind::Expr(PatExpr { + kind: PatExprKind::Lit { lit, negated: false }, .. }) = arm.pat.kind && let LitKind::Str(symbol, _) = lit.node diff --git a/src/tools/clippy/clippy_lints/src/matches/needless_match.rs b/src/tools/clippy/clippy_lints/src/matches/needless_match.rs index 63bea586caf61..0d5575efc2209 100644 --- a/src/tools/clippy/clippy_lints/src/matches/needless_match.rs +++ b/src/tools/clippy/clippy_lints/src/matches/needless_match.rs @@ -8,7 +8,7 @@ use clippy_utils::{ }; use rustc_errors::Applicability; use rustc_hir::LangItem::OptionNone; -use rustc_hir::{Arm, BindingMode, ByRef, Expr, ExprKind, ItemKind, Node, Pat, PatKind, Path, QPath}; +use rustc_hir::{Arm, BindingMode, ByRef, Expr, ExprKind, ItemKind, Node, Pat, PatExprKind, PatKind, Path, QPath}; use rustc_lint::LateContext; use rustc_span::sym; @@ -133,7 +133,7 @@ fn expr_ty_matches_p_ty(cx: &LateContext<'_>, expr: &Expr<'_>, p_expr: &Expr<'_> }, // compare match_expr ty with RetTy in `fn foo() -> RetTy` Node::Item(item) => { - if let ItemKind::Fn{ .. } = item.kind { + if let ItemKind::Fn { .. } = item.kind { let output = cx .tcx .fn_sig(item.owner_id) @@ -189,8 +189,12 @@ fn pat_same_as_expr(pat: &Pat<'_>, expr: &Expr<'_>) -> bool { }); }, // Example: `5 => 5` - (PatKind::Lit(pat_lit_expr), ExprKind::Lit(expr_spanned)) => { - if let ExprKind::Lit(pat_spanned) = &pat_lit_expr.kind { + (PatKind::Expr(pat_expr_expr), ExprKind::Lit(expr_spanned)) => { + if let PatExprKind::Lit { + lit: pat_spanned, + negated: false, + } = &pat_expr_expr.kind + { return pat_spanned.node == expr_spanned.node; } }, diff --git a/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs b/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs index 856311899f268..4a5d3c516b880 100644 --- a/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs +++ b/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs @@ -34,13 +34,13 @@ fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>) if let Arm { pat, guard: None, .. } = *arm { if let PatKind::Range(ref lhs, ref rhs, range_end) = pat.kind { let lhs_const = if let Some(lhs) = lhs { - ConstEvalCtxt::new(cx).eval(lhs)? + ConstEvalCtxt::new(cx).eval_pat_expr(lhs)? } else { let min_val_const = ty.numeric_min_val(cx.tcx)?; mir_to_const(cx.tcx, mir::Const::from_ty_const(min_val_const, ty, cx.tcx))? }; let rhs_const = if let Some(rhs) = rhs { - ConstEvalCtxt::new(cx).eval(rhs)? + ConstEvalCtxt::new(cx).eval_pat_expr(rhs)? } else { let max_val_const = ty.numeric_max_val(cx.tcx)?; mir_to_const(cx.tcx, mir::Const::from_ty_const(max_val_const, ty, cx.tcx))? @@ -57,8 +57,10 @@ fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>) }); } - if let PatKind::Lit(value) = pat.kind { - let value = ConstEvalCtxt::new(cx).eval_full_int(value)?; + if let PatKind::Expr(value) = pat.kind { + let value = ConstEvalCtxt::new(cx) + .eval_pat_expr(value)? + .int_value(cx.tcx, cx.typeck_results().node_type(pat.hir_id))?; return Some(SpannedRange { span: pat.span, node: (value, EndBound::Included(value)), diff --git a/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs b/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs index 264458a86ef49..7e74b36b44158 100644 --- a/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs +++ b/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs @@ -9,7 +9,7 @@ use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir::LangItem::{self, OptionNone, OptionSome, PollPending, PollReady, ResultErr, ResultOk}; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::{Arm, Expr, ExprKind, Node, Pat, PatKind, QPath, UnOp}; +use rustc_hir::{Arm, Expr, ExprKind, Node, Pat, PatExprKind, PatKind, QPath, UnOp}; use rustc_lint::LateContext; use rustc_middle::ty::{self, GenericArgKind, Ty}; use rustc_span::{Span, Symbol, sym}; @@ -74,8 +74,8 @@ fn find_match_true<'tcx>( span: Span, message: &'static str, ) { - if let PatKind::Lit(lit) = pat.kind - && let ExprKind::Lit(lit) = lit.kind + if let PatKind::Expr(lit) = pat.kind + && let PatExprKind::Lit { lit, negated: false } = lit.kind && let LitKind::Bool(pat_is_true) = lit.node { let mut applicability = Applicability::MachineApplicable; diff --git a/src/tools/clippy/clippy_lints/src/matches/single_match.rs b/src/tools/clippy/clippy_lints/src/matches/single_match.rs index 10ca6832d9c12..b1d0686ffc42e 100644 --- a/src/tools/clippy/clippy_lints/src/matches/single_match.rs +++ b/src/tools/clippy/clippy_lints/src/matches/single_match.rs @@ -9,7 +9,7 @@ use rustc_arena::DroplessArena; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::{Visitor, walk_pat}; -use rustc_hir::{Arm, Expr, ExprKind, HirId, Node, Pat, PatKind, QPath, StmtKind}; +use rustc_hir::{Arm, Expr, ExprKind, HirId, Node, Pat, PatExpr, PatExprKind, PatKind, QPath, StmtKind}; use rustc_lint::LateContext; use rustc_middle::ty::{self, AdtDef, TyCtxt, TypeckResults, VariantDef}; use rustc_span::{Span, sym}; @@ -114,7 +114,7 @@ fn report_single_pattern(cx: &LateContext<'_>, ex: &Expr<'_>, arm: &Arm<'_>, exp } let (pat, pat_ref_count) = peel_hir_pat_refs(arm.pat); - let (msg, sugg) = if let PatKind::Path(_) | PatKind::Lit(_) = pat.kind + let (msg, sugg) = if let PatKind::Path(_) | PatKind::Expr(_) = pat.kind && let (ty, ty_ref_count) = peel_middle_ty_refs(cx.typeck_results().expr_ty(ex)) && let Some(spe_trait_id) = cx.tcx.lang_items().structural_peq_trait() && let Some(pe_trait_id) = cx.tcx.lang_items().eq_trait() @@ -126,8 +126,8 @@ fn report_single_pattern(cx: &LateContext<'_>, ex: &Expr<'_>, arm: &Arm<'_>, exp // scrutinee derives PartialEq and the pattern is a constant. let pat_ref_count = match pat.kind { // string literals are already a reference. - PatKind::Lit(Expr { - kind: ExprKind::Lit(lit), + PatKind::Expr(PatExpr { + kind: PatExprKind::Lit { lit, negated: false }, .. }) if lit.node.is_str() || lit.node.is_bytestr() => pat_ref_count + 1, _ => pat_ref_count, @@ -384,7 +384,7 @@ impl<'a> PatState<'a> { PatKind::Wild | PatKind::Binding(_, _, _, None) - | PatKind::Lit(_) + | PatKind::Expr(_) | PatKind::Range(..) | PatKind::Path(_) | PatKind::Never diff --git a/src/tools/clippy/clippy_lints/src/string_patterns.rs b/src/tools/clippy/clippy_lints/src/string_patterns.rs index 0d85b1b858a4f..3834087f79779 100644 --- a/src/tools/clippy/clippy_lints/src/string_patterns.rs +++ b/src/tools/clippy/clippy_lints/src/string_patterns.rs @@ -11,7 +11,7 @@ use clippy_utils::visitors::{Descend, for_each_expr}; use itertools::Itertools; use rustc_ast::{BinOpKind, LitKind}; use rustc_errors::Applicability; -use rustc_hir::{Expr, ExprKind, PatKind}; +use rustc_hir::{Expr, ExprKind, PatExprKind, PatKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; use rustc_session::impl_lint_pass; @@ -171,7 +171,7 @@ fn check_manual_pattern_char_comparison(cx: &LateContext<'_>, method_arg: &Expr< return ControlFlow::Break(()); } if arm.pat.walk_short(|pat| match pat.kind { - PatKind::Lit(expr) if let ExprKind::Lit(lit) = expr.kind => { + PatKind::Expr(expr) if let PatExprKind::Lit { lit, negated: false } = expr.kind => { if let LitKind::Char(_) = lit.node { set_char_spans.push(lit.span); } diff --git a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs index 50a97579df779..8923484bb58f0 100644 --- a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs +++ b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs @@ -92,7 +92,7 @@ impl EarlyLintPass for UnnestedOrPatterns { } fn lint_unnested_or_patterns(cx: &EarlyContext<'_>, pat: &Pat) { - if let Ident(.., None) | Lit(_) | Wild | Path(..) | Range(..) | Rest | MacCall(_) = pat.kind { + if let Ident(.., None) | Expr(_) | Wild | Path(..) | Range(..) | Rest | MacCall(_) = pat.kind { // This is a leaf pattern, so cloning is unprofitable. return; } @@ -228,7 +228,7 @@ fn transform_with_focus_on_idx(alternatives: &mut ThinVec>, focus_idx: us // Therefore they are not some form of constructor `C`, // with which a pattern `C(p_0)` may be formed, // which we would want to join with other `C(p_j)`s. - Ident(.., None) | Lit(_) | Wild | Err(_) | Never | Path(..) | Range(..) | Rest | MacCall(_) + Ident(.., None) | Expr(_) | Wild | Err(_) | Never | Path(..) | Range(..) | Rest | MacCall(_) // Skip immutable refs, as grouping them saves few characters, // and almost always requires adding parens (increasing noisiness). // In the case of only two patterns, replacement adds net characters. diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs index c2dcb5ae1f9e5..4dcc8ac7fb0af 100644 --- a/src/tools/clippy/clippy_lints/src/utils/author.rs +++ b/src/tools/clippy/clippy_lints/src/utils/author.rs @@ -4,7 +4,7 @@ use rustc_ast::ast::{LitFloatType, LitKind}; use rustc_data_structures::fx::FxHashMap; use rustc_hir::{ self as hir, BindingMode, CaptureBy, Closure, ClosureKind, ConstArg, ConstArgKind, CoroutineKind, ExprKind, - FnRetTy, HirId, Lit, PatKind, QPath, StmtKind, StructTailExpr, TyKind, + FnRetTy, HirId, Lit, PatExprKind, PatKind, QPath, StmtKind, StructTailExpr, TyKind, }; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::declare_lint_pass; @@ -643,6 +643,27 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { self.expr(expr); } + fn pat_expr(&self, lit: &Binding<&hir::PatExpr<'_>>) { + let kind = |kind| chain!(self, "let PatExprKind::{kind} = {lit}.kind"); + macro_rules! kind { + ($($t:tt)*) => (kind(format_args!($($t)*))); + } + match lit.value.kind { + PatExprKind::Lit { lit, negated } => { + bind!(self, lit); + bind!(self, negated); + kind!("Lit{{ref {lit}, {negated} }}"); + self.lit(lit); + }, + PatExprKind::ConstBlock(_) => kind!("ConstBlock(_)"), + PatExprKind::Path(ref qpath) => { + bind!(self, qpath); + kind!("Path(ref {qpath})"); + self.qpath(qpath); + }, + } + } + fn pat(&self, pat: &Binding<&hir::Pat<'_>>) { let kind = |kind| chain!(self, "let PatKind::{kind} = {pat}.kind"); macro_rules! kind { @@ -717,17 +738,17 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { kind!("Guard({pat}, {cond})"); self.pat(pat); self.expr(cond); - } - PatKind::Lit(lit_expr) => { + }, + PatKind::Expr(lit_expr) => { bind!(self, lit_expr); - kind!("Lit({lit_expr})"); - self.expr(lit_expr); + kind!("Expr({lit_expr})"); + self.pat_expr(lit_expr); }, PatKind::Range(start, end, end_kind) => { opt_bind!(self, start, end); kind!("Range({start}, {end}, RangeEnd::{end_kind:?})"); - start.if_some(|e| self.expr(e)); - end.if_some(|e| self.expr(e)); + start.if_some(|e| self.pat_expr(e)); + end.if_some(|e| self.pat_expr(e)); }, PatKind::Slice(start, middle, end) => { bind!(self, start, end); diff --git a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs index 623d9c7608612..2eb09bac8d881 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs @@ -36,7 +36,7 @@ pub fn eq_pat(l: &Pat, r: &Pat) -> bool { (Paren(l), _) => eq_pat(l, r), (_, Paren(r)) => eq_pat(l, r), (Wild, Wild) | (Rest, Rest) => true, - (Lit(l), Lit(r)) => eq_expr(l, r), + (Expr(l), Expr(r)) => eq_expr(l, r), (Ident(b1, i1, s1), Ident(b2, i2, s2)) => { b1 == b2 && eq_id(*i1, *i2) && both(s1.as_deref(), s2.as_deref(), eq_pat) }, diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs index 43ddf06730dd2..d46beddf73124 100644 --- a/src/tools/clippy/clippy_utils/src/consts.rs +++ b/src/tools/clippy/clippy_utils/src/consts.rs @@ -4,7 +4,6 @@ //! executable MIR bodies, so we have to do this instead. #![allow(clippy::float_cmp)] -use crate::macros::HirNode; use crate::source::{SpanRangeExt, walk_span_to_context}; use crate::{clip, is_direct_expn_of, sext, unsext}; @@ -13,7 +12,7 @@ use rustc_apfloat::ieee::{Half, Quad}; use rustc_ast::ast::{self, LitFloatType, LitKind}; use rustc_data_structures::sync::Lrc; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::{BinOp, BinOpKind, Block, ConstBlock, Expr, ExprKind, HirId, Item, ItemKind, Node, QPath, UnOp}; +use rustc_hir::{BinOp, BinOpKind, Block, ConstBlock, Expr, ExprKind, HirId, Item, ItemKind, Node, QPath, UnOp, PatExpr, PatExprKind}; use rustc_lexer::tokenize; use rustc_lint::LateContext; use rustc_middle::mir::ConstValue; @@ -442,30 +441,48 @@ impl<'tcx> ConstEvalCtxt<'tcx> { } } + pub fn eval_pat_expr(&self, pat_expr: &PatExpr<'_>) -> Option> { + match &pat_expr.kind { + PatExprKind::Lit { lit, negated } => { + let ty = self.typeck.node_type_opt(pat_expr.hir_id); + let val = lit_to_mir_constant(&lit.node, ty); + if *negated { + self.constant_negate(&val, ty?) + } else { + Some(val) + } + } + PatExprKind::ConstBlock(ConstBlock { body, ..}) => self.expr(self.tcx.hir().body(*body).value), + PatExprKind::Path(qpath) => self.qpath(qpath, pat_expr.hir_id), + } + } + + fn qpath(&self, qpath: &QPath<'_>, hir_id: HirId) -> Option> { + let is_core_crate = if let Some(def_id) = self.typeck.qpath_res(qpath, hir_id).opt_def_id() { + self.tcx.crate_name(def_id.krate) == sym::core + } else { + false + }; + self.fetch_path_and_apply(qpath, hir_id, self.typeck.node_type(hir_id), |self_, result| { + let result = mir_to_const(self_.tcx, result)?; + // If source is already Constant we wouldn't want to override it with CoreConstant + self_.source.set( + if is_core_crate && !matches!(self_.source.get(), ConstantSource::Constant) { + ConstantSource::CoreConstant + } else { + ConstantSource::Constant + }, + ); + Some(result) + }) + } + /// Simple constant folding: Insert an expression, get a constant or none. fn expr(&self, e: &Expr<'_>) -> Option> { match e.kind { ExprKind::ConstBlock(ConstBlock { body, .. }) => self.expr(self.tcx.hir().body(body).value), ExprKind::DropTemps(e) => self.expr(e), - ExprKind::Path(ref qpath) => { - let is_core_crate = if let Some(def_id) = self.typeck.qpath_res(qpath, e.hir_id()).opt_def_id() { - self.tcx.crate_name(def_id.krate) == sym::core - } else { - false - }; - self.fetch_path_and_apply(qpath, e.hir_id, self.typeck.expr_ty(e), |self_, result| { - let result = mir_to_const(self_.tcx, result)?; - // If source is already Constant we wouldn't want to override it with CoreConstant - self_.source.set( - if is_core_crate && !matches!(self_.source.get(), ConstantSource::Constant) { - ConstantSource::CoreConstant - } else { - ConstantSource::Constant - }, - ); - Some(result) - }) - }, + ExprKind::Path(ref qpath) => self.qpath(qpath, e.hir_id), ExprKind::Block(block, _) => self.block(block), ExprKind::Lit(lit) => { if is_direct_expn_of(e.span, "cfg").is_some() { diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index 7c4e834f8416f..d1d0abd469093 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -9,8 +9,8 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::{ AssocItemConstraint, BinOpKind, BindingMode, Block, BodyId, Closure, ConstArg, ConstArgKind, Expr, ExprField, ExprKind, FnRetTy, GenericArg, GenericArgs, HirId, HirIdMap, InlineAsmOperand, LetExpr, Lifetime, LifetimeName, - Pat, PatField, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, StructTailExpr, TraitBoundModifiers, Ty, - TyKind, + Pat, PatExpr, PatExprKind, PatField, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, StructTailExpr, + TraitBoundModifiers, Ty, TyKind, }; use rustc_lexer::{TokenKind, tokenize}; use rustc_lint::LateContext; @@ -489,6 +489,24 @@ impl HirEqInterExpr<'_, '_, '_> { li.name == ri.name && self.eq_pat(lp, rp) } + fn eq_pat_expr(&mut self, left: &PatExpr<'_>, right: &PatExpr<'_>) -> bool { + match (&left.kind, &right.kind) { + ( + &PatExprKind::Lit { + lit: left, + negated: left_neg, + }, + &PatExprKind::Lit { + lit: right, + negated: right_neg, + }, + ) => left_neg == right_neg && left.node == right.node, + (PatExprKind::ConstBlock(left), PatExprKind::ConstBlock(right)) => self.eq_body(left.body, right.body), + (PatExprKind::Path(left), PatExprKind::Path(right)) => self.eq_qpath(left, right), + (PatExprKind::Lit { .. } | PatExprKind::ConstBlock(..) | PatExprKind::Path(..), _) => false, + } + } + /// Checks whether two patterns are the same. fn eq_pat(&mut self, left: &Pat<'_>, right: &Pat<'_>) -> bool { match (&left.kind, &right.kind) { @@ -507,11 +525,11 @@ impl HirEqInterExpr<'_, '_, '_> { eq }, (PatKind::Path(l), PatKind::Path(r)) => self.eq_qpath(l, r), - (&PatKind::Lit(l), &PatKind::Lit(r)) => self.eq_expr(l, r), + (&PatKind::Expr(l), &PatKind::Expr(r)) => self.eq_pat_expr(l, r), (&PatKind::Tuple(l, ls), &PatKind::Tuple(r, rs)) => ls == rs && over(l, r, |l, r| self.eq_pat(l, r)), (&PatKind::Range(ref ls, ref le, li), &PatKind::Range(ref rs, ref re, ri)) => { - both(ls.as_ref(), rs.as_ref(), |a, b| self.eq_expr(a, b)) - && both(le.as_ref(), re.as_ref(), |a, b| self.eq_expr(a, b)) + both(ls.as_ref(), rs.as_ref(), |a, b| self.eq_pat_expr(a, b)) + && both(le.as_ref(), re.as_ref(), |a, b| self.eq_pat_expr(a, b)) && (li == ri) }, (&PatKind::Ref(le, ref lm), &PatKind::Ref(re, ref rm)) => lm == rm && self.eq_pat(le, re), @@ -1073,6 +1091,18 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { // self.maybe_typeck_results.unwrap().qpath_res(p, id).hash(&mut self.s); } + pub fn hash_pat_expr(&mut self, lit: &PatExpr<'_>) { + std::mem::discriminant(&lit.kind).hash(&mut self.s); + match &lit.kind { + PatExprKind::Lit { lit, negated } => { + lit.node.hash(&mut self.s); + negated.hash(&mut self.s); + }, + PatExprKind::ConstBlock(c) => self.hash_body(c.body), + PatExprKind::Path(qpath) => self.hash_qpath(qpath), + } + } + pub fn hash_pat(&mut self, pat: &Pat<'_>) { std::mem::discriminant(&pat.kind).hash(&mut self.s); match pat.kind { @@ -1084,7 +1114,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { } }, PatKind::Box(pat) | PatKind::Deref(pat) => self.hash_pat(pat), - PatKind::Lit(expr) => self.hash_expr(expr), + PatKind::Expr(expr) => self.hash_pat_expr(expr), PatKind::Or(pats) => { for pat in pats { self.hash_pat(pat); @@ -1093,10 +1123,10 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { PatKind::Path(ref qpath) => self.hash_qpath(qpath), PatKind::Range(s, e, i) => { if let Some(s) = s { - self.hash_expr(s); + self.hash_pat_expr(s); } if let Some(e) = e { - self.hash_expr(e); + self.hash_pat_expr(e); } std::mem::discriminant(&i).hash(&mut self.s); }, diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index ba4a0f44584ef..d42e40acbc081 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -1777,7 +1777,7 @@ pub fn is_refutable(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool { }, } }, - PatKind::Lit(..) | PatKind::Range(..) | PatKind::Err(_) | PatKind::Deref(_) | PatKind::Guard(..) => true, + PatKind::Expr(..) | PatKind::Range(..) | PatKind::Err(_) | PatKind::Deref(_) | PatKind::Guard(..) => true, } } diff --git a/src/tools/clippy/tests/ui/author/if.stdout b/src/tools/clippy/tests/ui/author/if.stdout index a85dcddd3315f..8ffdf8862027b 100644 --- a/src/tools/clippy/tests/ui/author/if.stdout +++ b/src/tools/clippy/tests/ui/author/if.stdout @@ -30,8 +30,8 @@ if let StmtKind::Let(local) = stmt.kind } if let ExprKind::If(cond, then, Some(else_expr)) = expr.kind && let ExprKind::Let(let_expr) = cond.kind - && let PatKind::Lit(lit_expr) = let_expr.pat.kind - && let ExprKind::Lit(ref lit) = lit_expr.kind + && let PatKind::Expr(lit_expr) = let_expr.pat.kind + && let PatExprKind::Lit{ref lit, negated } = lit_expr.kind && let LitKind::Bool(true) = lit.node && let ExprKind::Path(ref qpath) = let_expr.init.kind && match_qpath(qpath, &["a"]) diff --git a/src/tools/clippy/tests/ui/author/loop.stdout b/src/tools/clippy/tests/ui/author/loop.stdout index 609d24910610c..c94eb171f52b9 100644 --- a/src/tools/clippy/tests/ui/author/loop.stdout +++ b/src/tools/clippy/tests/ui/author/loop.stdout @@ -76,8 +76,8 @@ if let Some(higher::While { condition: condition, body: body }) = higher::While: // report your lint here } if let Some(higher::WhileLet { let_pat: let_pat, let_expr: let_expr, if_then: if_then }) = higher::WhileLet::hir(expr) - && let PatKind::Lit(lit_expr) = let_pat.kind - && let ExprKind::Lit(ref lit) = lit_expr.kind + && let PatKind::Expr(lit_expr) = let_pat.kind + && let PatExprKind::Lit{ref lit, negated } = lit_expr.kind && let LitKind::Bool(true) = lit.node && let ExprKind::Path(ref qpath) = let_expr.kind && match_qpath(qpath, &["a"]) diff --git a/src/tools/clippy/tests/ui/author/matches.stdout b/src/tools/clippy/tests/ui/author/matches.stdout index 91b3b6f6877eb..acb3b140dfa13 100644 --- a/src/tools/clippy/tests/ui/author/matches.stdout +++ b/src/tools/clippy/tests/ui/author/matches.stdout @@ -4,14 +4,14 @@ if let StmtKind::Let(local) = stmt.kind && let ExprKind::Lit(ref lit) = scrutinee.kind && let LitKind::Int(42, LitIntType::Unsuffixed) = lit.node && arms.len() == 3 - && let PatKind::Lit(lit_expr) = arms[0].pat.kind - && let ExprKind::Lit(ref lit1) = lit_expr.kind + && let PatKind::Expr(lit_expr) = arms[0].pat.kind + && let PatExprKind::Lit{ref lit1, negated } = lit_expr.kind && let LitKind::Int(16, LitIntType::Unsuffixed) = lit1.node && arms[0].guard.is_none() && let ExprKind::Lit(ref lit2) = arms[0].body.kind && let LitKind::Int(5, LitIntType::Unsuffixed) = lit2.node - && let PatKind::Lit(lit_expr1) = arms[1].pat.kind - && let ExprKind::Lit(ref lit3) = lit_expr1.kind + && let PatKind::Expr(lit_expr1) = arms[1].pat.kind + && let PatExprKind::Lit{ref lit3, negated1 } = lit_expr1.kind && let LitKind::Int(17, LitIntType::Unsuffixed) = lit3.node && arms[1].guard.is_none() && let ExprKind::Block(block, None) = arms[1].body.kind diff --git a/src/tools/clippy/tests/ui/author/struct.stdout b/src/tools/clippy/tests/ui/author/struct.stdout index 0b332d5e7d0e1..b66bbccb3cf1b 100644 --- a/src/tools/clippy/tests/ui/author/struct.stdout +++ b/src/tools/clippy/tests/ui/author/struct.stdout @@ -23,8 +23,8 @@ if let PatKind::Struct(ref qpath, fields, false) = arm.pat.kind && match_qpath(qpath, &["Test"]) && fields.len() == 1 && fields[0].ident.as_str() == "field" - && let PatKind::Lit(lit_expr) = fields[0].pat.kind - && let ExprKind::Lit(ref lit) = lit_expr.kind + && let PatKind::Expr(lit_expr) = fields[0].pat.kind + && let PatExprKind::Lit{ref lit, negated } = lit_expr.kind && let LitKind::Int(1, LitIntType::Unsuffixed) = lit.node && arm.guard.is_none() && let ExprKind::Block(block, None) = arm.body.kind @@ -36,8 +36,8 @@ if let PatKind::Struct(ref qpath, fields, false) = arm.pat.kind if let PatKind::TupleStruct(ref qpath, fields, None) = arm.pat.kind && match_qpath(qpath, &["TestTuple"]) && fields.len() == 1 - && let PatKind::Lit(lit_expr) = fields[0].kind - && let ExprKind::Lit(ref lit) = lit_expr.kind + && let PatKind::Expr(lit_expr) = fields[0].kind + && let PatExprKind::Lit{ref lit, negated } = lit_expr.kind && let LitKind::Int(1, LitIntType::Unsuffixed) = lit.node && arm.guard.is_none() && let ExprKind::Block(block, None) = arm.body.kind diff --git a/src/tools/rustfmt/src/patterns.rs b/src/tools/rustfmt/src/patterns.rs index 7b4730eadc854..b55469f332aa1 100644 --- a/src/tools/rustfmt/src/patterns.rs +++ b/src/tools/rustfmt/src/patterns.rs @@ -42,7 +42,7 @@ fn is_short_pattern_inner(pat: &ast::Pat) -> bool { | ast::PatKind::Never | ast::PatKind::Wild | ast::PatKind::Err(_) - | ast::PatKind::Lit(_) => true, + | ast::PatKind::Expr(_) => true, ast::PatKind::Ident(_, _, ref pat) => pat.is_none(), ast::PatKind::Struct(..) | ast::PatKind::MacCall(..) @@ -293,7 +293,7 @@ impl Rewrite for Pat { let path_str = rewrite_path(context, PathContext::Expr, q_self, path, shape)?; rewrite_tuple_pat(pat_vec, Some(path_str), self.span, context, shape) } - PatKind::Lit(ref expr) => expr.rewrite_result(context, shape), + PatKind::Expr(ref expr) => expr.rewrite_result(context, shape), PatKind::Slice(ref slice_pat) if context.config.style_edition() <= StyleEdition::Edition2021 => { @@ -530,7 +530,7 @@ pub(crate) fn can_be_overflowed_pat( ast::PatKind::Ref(ref p, _) | ast::PatKind::Box(ref p) => { can_be_overflowed_pat(context, &TuplePatField::Pat(p), len) } - ast::PatKind::Lit(ref expr) => can_be_overflowed_expr(context, expr, len), + ast::PatKind::Expr(ref expr) => can_be_overflowed_expr(context, expr, len), _ => false, }, TuplePatField::Dotdot(..) => false, diff --git a/tests/ui/macros/stringify.rs b/tests/ui/macros/stringify.rs index a560bf4c6ef43..40033f546d30b 100644 --- a/tests/ui/macros/stringify.rs +++ b/tests/ui/macros/stringify.rs @@ -569,7 +569,7 @@ fn test_pat() { c1!(pat, [ &pat ], "&pat"); c1!(pat, [ &mut pat ], "&mut pat"); - // PatKind::Lit + // PatKind::Expr c1!(pat, [ 1_000_i8 ], "1_000_i8"); // PatKind::Range diff --git a/tests/ui/pattern/patkind-litrange-no-expr.rs b/tests/ui/pattern/patkind-litrange-no-expr.rs index 7ef541cb58528..14d7dc737d652 100644 --- a/tests/ui/pattern/patkind-litrange-no-expr.rs +++ b/tests/ui/pattern/patkind-litrange-no-expr.rs @@ -6,7 +6,7 @@ macro_rules! enum_number { fn foo(value: i32) -> Option<$name> { match value { - $( $value => Some($name::$variant), )* // PatKind::Lit + $( $value => Some($name::$variant), )* // PatKind::Expr $( $value ..= 42 => Some($name::$variant), )* // PatKind::Range _ => None } diff --git a/tests/ui/pattern/struct-pattern-on-non-struct-resolve-error.rs b/tests/ui/pattern/struct-pattern-on-non-struct-resolve-error.rs new file mode 100644 index 0000000000000..17a5bad0e6c0f --- /dev/null +++ b/tests/ui/pattern/struct-pattern-on-non-struct-resolve-error.rs @@ -0,0 +1,10 @@ +// Regression test for #135209. +// We ensure that we don't try to access fields on a non-struct pattern type. +fn main() { + if let as Iterator>::Item { .. } = 1 { + //~^ ERROR E0658 + //~| ERROR E0071 + //~| ERROR E0277 + x //~ ERROR E0425 + } +} diff --git a/tests/ui/pattern/struct-pattern-on-non-struct-resolve-error.stderr b/tests/ui/pattern/struct-pattern-on-non-struct-resolve-error.stderr new file mode 100644 index 0000000000000..793c2d1e97fc0 --- /dev/null +++ b/tests/ui/pattern/struct-pattern-on-non-struct-resolve-error.stderr @@ -0,0 +1,34 @@ +error[E0425]: cannot find value `x` in this scope + --> $DIR/struct-pattern-on-non-struct-resolve-error.rs:8:9 + | +LL | x + | ^ not found in this scope + +error[E0658]: usage of qualified paths in this context is experimental + --> $DIR/struct-pattern-on-non-struct-resolve-error.rs:4:12 + | +LL | if let as Iterator>::Item { .. } = 1 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #86935 for more information + = help: add `#![feature(more_qualified_paths)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0071]: expected struct, variant or union type, found inferred type + --> $DIR/struct-pattern-on-non-struct-resolve-error.rs:4:12 + | +LL | if let as Iterator>::Item { .. } = 1 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a struct + +error[E0277]: `Vec<()>` is not an iterator + --> $DIR/struct-pattern-on-non-struct-resolve-error.rs:4:12 + | +LL | if let as Iterator>::Item { .. } = 1 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Vec<()>` is not an iterator + | + = help: the trait `Iterator` is not implemented for `Vec<()>` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0071, E0277, E0425, E0658. +For more information about an error, try `rustc --explain E0071`. diff --git a/tests/ui/pattern/struct-pattern-with-missing-fields-resolve-error.rs b/tests/ui/pattern/struct-pattern-with-missing-fields-resolve-error.rs index 225891e390ff5..39f9f5a2c0208 100644 --- a/tests/ui/pattern/struct-pattern-with-missing-fields-resolve-error.rs +++ b/tests/ui/pattern/struct-pattern-with-missing-fields-resolve-error.rs @@ -3,6 +3,10 @@ struct Website { title: Option, } +enum Foo { + Bar { a: i32 }, +} + fn main() { let website = Website { url: "http://www.example.com".into(), @@ -18,4 +22,9 @@ fn main() { println!("[{}]({})", title, url); //~ ERROR cannot find value `title` in this scope //~^ NOTE not found in this scope } + + let x = Foo::Bar { a: 1 }; + if let Foo::Bar { .. } = x { //~ NOTE this pattern + println!("{a}"); //~ ERROR cannot find value `a` in this scope + } } diff --git a/tests/ui/pattern/struct-pattern-with-missing-fields-resolve-error.stderr b/tests/ui/pattern/struct-pattern-with-missing-fields-resolve-error.stderr index 80fcd714400d6..b985b771754ee 100644 --- a/tests/ui/pattern/struct-pattern-with-missing-fields-resolve-error.stderr +++ b/tests/ui/pattern/struct-pattern-with-missing-fields-resolve-error.stderr @@ -1,5 +1,5 @@ error: expected `,` - --> $DIR/struct-pattern-with-missing-fields-resolve-error.rs:12:31 + --> $DIR/struct-pattern-with-missing-fields-resolve-error.rs:16:31 | LL | if let Website { url, Some(title) } = website { | ------- ^ @@ -7,13 +7,21 @@ LL | if let Website { url, Some(title) } = website { | while parsing the fields for this pattern error[E0425]: cannot find value `title` in this scope - --> $DIR/struct-pattern-with-missing-fields-resolve-error.rs:18:30 + --> $DIR/struct-pattern-with-missing-fields-resolve-error.rs:22:30 | LL | if let Website { url, .. } = website { | ------------------- this pattern doesn't include `title`, which is available in `Website` LL | println!("[{}]({})", title, url); | ^^^^^ not found in this scope -error: aborting due to 2 previous errors +error[E0425]: cannot find value `a` in this scope + --> $DIR/struct-pattern-with-missing-fields-resolve-error.rs:28:20 + | +LL | if let Foo::Bar { .. } = x { + | --------------- this pattern doesn't include `a`, which is available in `Bar` +LL | println!("{a}"); + | ^ help: a local variable with a similar name exists: `x` + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/unpretty/expanded-exhaustive.rs b/tests/ui/unpretty/expanded-exhaustive.rs index e052627e71cfe..26c253d049b24 100644 --- a/tests/ui/unpretty/expanded-exhaustive.rs +++ b/tests/ui/unpretty/expanded-exhaustive.rs @@ -651,8 +651,8 @@ mod patterns { let &mut pat; } - /// PatKind::Lit - fn pat_lit() { + /// PatKind::Expr + fn pat_expr() { let 1_000_i8; let -""; } diff --git a/tests/ui/unpretty/expanded-exhaustive.stdout b/tests/ui/unpretty/expanded-exhaustive.stdout index 132d00cd8edd5..bd7aa1117cce1 100644 --- a/tests/ui/unpretty/expanded-exhaustive.stdout +++ b/tests/ui/unpretty/expanded-exhaustive.stdout @@ -567,8 +567,8 @@ mod patterns { fn pat_deref() { let deref!(pat); } /// PatKind::Ref fn pat_ref() { let &pat; let &mut pat; } - /// PatKind::Lit - fn pat_lit() { let 1_000_i8; let -""; } + /// PatKind::Expr + fn pat_expr() { let 1_000_i8; let -""; } /// PatKind::Range fn pat_range() { let ..1; let 0..; let 0..1; let 0..=1; let -2..=-1; } /// PatKind::Slice diff --git a/tests/ui/unpretty/unpretty-expr-fn-arg.stdout b/tests/ui/unpretty/unpretty-expr-fn-arg.stdout index c424b1afa3465..43aa93c83bd31 100644 --- a/tests/ui/unpretty/unpretty-expr-fn-arg.stdout +++ b/tests/ui/unpretty/unpretty-expr-fn-arg.stdout @@ -14,4 +14,4 @@ extern crate std; fn main() ({ } as ()) -fn foo((-(128 as i8) as i8)...(127 as i8): i8) ({ } as ()) +fn foo(-128...127: i8) ({ } as ()) diff --git a/triagebot.toml b/triagebot.toml index 7241b448c487f..67412d9e60b05 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -420,13 +420,20 @@ trigger_files = [ [autolabel."A-testsuite"] trigger_files = [ + "src/bootstrap/src/core/build_steps/test.rs", "src/ci", - "src/tools/compiletest", "src/tools/cargotest", - "src/tools/tidy", + "src/tools/compiletest", + "src/tools/miropt-test-tools", "src/tools/remote-test-server", "src/tools/remote-test-client", - "src/tools/tier-check" + "src/tools/rustdoc-gui-test", + "src/tools/suggest-tests", +] + +[autolabel."A-tidy"] +trigger_files = [ + "src/tools/tidy", ] [autolabel."A-meta"]