diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index c2bfb3033195e..fa29fb76c51a8 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1557,12 +1557,10 @@ impl Expr { } match &self.kind { - ExprKind::Closure(closure) => { - match closure.fn_decl.output { - FnRetTy::Default(_) => ExprPrecedence::Jump, - FnRetTy::Ty(_) => prefix_attrs_precedence(&self.attrs), - } - } + ExprKind::Closure(closure) => match closure.fn_decl.output { + FnRetTy::Default(_) => ExprPrecedence::Jump, + FnRetTy::Ty(_) => prefix_attrs_precedence(&self.attrs), + }, ExprKind::Break(_ /*label*/, value) | ExprKind::Ret(value) @@ -1584,18 +1582,16 @@ impl Expr { ExprKind::Binary(op, ..) => op.node.precedence(), ExprKind::Cast(..) => ExprPrecedence::Cast, - ExprKind::Assign(..) | - ExprKind::AssignOp(..) => ExprPrecedence::Assign, + ExprKind::Assign(..) | ExprKind::AssignOp(..) => ExprPrecedence::Assign, // Unary, prefix - ExprKind::AddrOf(..) + ExprKind::AddrOf(..) => ExprPrecedence::Prefix, + // Here `let pats = expr` has `let pats =` as a "unary" prefix of `expr`. // However, this is not exactly right. When `let _ = a` is the LHS of a binop we // need parens sometimes. E.g. we can print `(let _ = a) && b` as `let _ = a && b` // but we need to print `(let _ = a) < b` as-is with parens. - | ExprKind::Let(..) - | ExprKind::Move(..) - | ExprKind::Unary(..) => ExprPrecedence::Prefix, + ExprKind::Let(..) | ExprKind::Move(..) | ExprKind::Unary(..) => ExprPrecedence::Prefix, // Need parens if and only if there are prefix attributes. ExprKind::Array(_) diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 743e60d2f3bb2..e1746039963f4 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -688,10 +688,10 @@ impl Token { Lifetime(..) | // labeled loop Pound => true, // expression attributes OpenInvisible(InvisibleOrigin::MetaVar( - MetaVarKind::Block | - MetaVarKind::Expr { .. } | - MetaVarKind::Literal | - MetaVarKind::Path + MetaVarKind::Block + | MetaVarKind::Expr { .. } + | MetaVarKind::Literal + | MetaVarKind::Path, )) => true, _ => false, } @@ -717,12 +717,12 @@ impl Token { Shl => true, // path (double UFCS) Or => matches!(pat_kind, PatWithOr), // leading vert `|` or-pattern OpenInvisible(InvisibleOrigin::MetaVar( - MetaVarKind::Expr { .. } | - MetaVarKind::Literal | - MetaVarKind::Meta { .. } | - MetaVarKind::Pat(_) | - MetaVarKind::Path | - MetaVarKind::Ty { .. } + MetaVarKind::Expr { .. } + | MetaVarKind::Literal + | MetaVarKind::Meta { .. } + | MetaVarKind::Pat(_) + | MetaVarKind::Path + | MetaVarKind::Ty { .. }, )) => true, _ => false, } @@ -733,20 +733,19 @@ impl Token { match self.uninterpolate().kind { Ident(name, is_raw) => ident_can_begin_type(name, self.span, is_raw), // type name or keyword - OpenParen | // tuple - OpenBracket | // array - Bang | // never - Star | // raw pointer - And | // reference - AndAnd | // double reference - Question | // maybe bound in trait object - Lifetime(..) | // lifetime bound in trait object - Lt | Shl | // associated path - PathSep => true, // global path - OpenInvisible(InvisibleOrigin::MetaVar( - MetaVarKind::Ty { .. } | - MetaVarKind::Path - )) => true, + OpenParen // tuple + | OpenBracket // array + | Bang // never + | Star // raw pointer + | And // reference + | AndAnd // double reference + | Question // maybe bound in trait object + | Lifetime(..) // lifetime bound in trait object + | Lt | Shl // associated path + | PathSep => true, // global path + OpenInvisible(InvisibleOrigin::MetaVar(MetaVarKind::Ty { .. } | MetaVarKind::Path)) => { + true + } // For anonymous structs or unions, which only appear in specific positions // (type of struct fields or union fields), we don't consider them as regular types _ => false, diff --git a/compiler/rustc_borrowck/src/def_use.rs b/compiler/rustc_borrowck/src/def_use.rs index 502265a83523e..8813ef5249262 100644 --- a/compiler/rustc_borrowck/src/def_use.rs +++ b/compiler/rustc_borrowck/src/def_use.rs @@ -60,8 +60,7 @@ pub(crate) fn categorize(context: PlaceContext) -> Option { PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect) | PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) | PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) | - PlaceContext::MutatingUse(MutatingUseContext::Retag) => - Some(DefUse::Use), + PlaceContext::MutatingUse(MutatingUseContext::Retag) => Some(DefUse::Use), /////////////////////////////////////////////////////////////////////////// // DROP USES @@ -70,9 +69,7 @@ pub(crate) fn categorize(context: PlaceContext) -> Option { // call to `std::mem::drop()`). For the purposes of NLL, // uses in drop are special because `#[may_dangle]` // attributes can affect whether lifetimes must be live. - - PlaceContext::MutatingUse(MutatingUseContext::Drop) => - Some(DefUse::Drop), + PlaceContext::MutatingUse(MutatingUseContext::Drop) => Some(DefUse::Drop), // Debug info is neither def nor use. PlaceContext::NonUse(NonUseContext::VarDebugInfo) => None, diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 8b9f4291603a9..e80969cd0cbb2 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -833,19 +833,21 @@ impl<'a, 'tcx> ResultsVisitor<'tcx, Borrowck<'a, 'tcx>> for MirBorrowckCtxt<'a, NonDivergingIntrinsic::CopyNonOverlapping(..) => span_bug!( span, "Unexpected CopyNonOverlapping, should only appear after lower_intrinsics", - ) - } + ), + }, // Only relevant for mir typeck - StatementKind::AscribeUserType(..) + StatementKind::AscribeUserType(..) => {} // Only relevant for liveness and unsafeck - | StatementKind::PlaceMention(..) + StatementKind::PlaceMention(..) => {} // Doesn't have any language semantics - | StatementKind::Coverage(..) + StatementKind::Coverage(..) => {} // These do not actually affect borrowck - | StatementKind::ConstEvalCounter - | StatementKind::StorageLive(..) => {} + StatementKind::ConstEvalCounter | StatementKind::StorageLive(..) => {} // This does not affect borrowck - StatementKind::BackwardIncompatibleDropHint { place, reason: BackwardIncompatibleDropReason::Edition2024 } => { + StatementKind::BackwardIncompatibleDropHint { + place, + reason: BackwardIncompatibleDropReason::Edition2024, + } => { self.check_backward_incompatible_drop(location, **place, state); } StatementKind::StorageDead(local) => { @@ -857,8 +859,7 @@ impl<'a, 'tcx> ResultsVisitor<'tcx, Borrowck<'a, 'tcx>> for MirBorrowckCtxt<'a, state, ); } - StatementKind::Nop - | StatementKind::SetDiscriminant { .. } => { + StatementKind::Nop | StatementKind::SetDiscriminant { .. } => { bug!("Statement not allowed in this MIR phase") } } @@ -2238,15 +2239,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> { // None case => assigning to `x` does not require `x` be initialized. for (place_base, elem) in place.iter_projections().rev() { match elem { - ProjectionElem::Index(_/*operand*/) | - ProjectionElem::OpaqueCast(_) | - ProjectionElem::ConstantIndex { .. } | + ProjectionElem::Index(_/*operand*/) + | ProjectionElem::OpaqueCast(_) // assigning to P[i] requires P to be valid. - ProjectionElem::Downcast(_/*adt_def*/, _/*variant_idx*/) => + | ProjectionElem::ConstantIndex { .. } // assigning to (P->variant) is okay if assigning to `P` is okay // // FIXME: is this true even if P is an adt with a dtor? - { } + | ProjectionElem::Downcast(_/*adt_def*/, _/*variant_idx*/) => + {} ProjectionElem::UnwrapUnsafeBinder(_) => { check_parent_of_field(self, location, place_base, span, state); @@ -2255,8 +2256,11 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> { // assigning to (*P) requires P to be initialized ProjectionElem::Deref => { self.check_if_full_path_is_moved( - location, InitializationRequiringAction::Use, - (place_base, span), state); + location, + InitializationRequiringAction::Use, + (place_base, span), + state, + ); // (base initialized; no need to // recur further) break; @@ -2275,8 +2279,11 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> { match base_ty.kind() { ty::Adt(def, _) if def.has_dtor(tcx) => { self.check_if_path_or_subpath_is_moved( - location, InitializationRequiringAction::Assignment, - (place_base, span), state); + location, + InitializationRequiringAction::Assignment, + (place_base, span), + state, + ); // (base initialized; no need to // recur further) diff --git a/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs b/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs index 31df87dabf815..5a33b2d5bbe5b 100644 --- a/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs +++ b/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs @@ -56,11 +56,9 @@ impl<'a, 'tcx> Visitor<'tcx> for LoanInvalidationsGenerator<'a, 'tcx> { StatementKind::Intrinsic(NonDivergingIntrinsic::Assume(op)) => { self.consume_operand(location, op); } - StatementKind::Intrinsic(NonDivergingIntrinsic::CopyNonOverlapping(CopyNonOverlapping { - src, - dst, - count, - })) => { + StatementKind::Intrinsic(NonDivergingIntrinsic::CopyNonOverlapping( + CopyNonOverlapping { src, dst, count }, + )) => { self.consume_operand(location, src); self.consume_operand(location, dst); self.consume_operand(location, count); diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index ec1eb7eeb6fc0..fc57310804873 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -26,7 +26,7 @@ use rustc_lint_defs::builtin::LINKER_INFO; use rustc_macros::{Decodable, Encodable}; use rustc_metadata::EncodedMetadata; use rustc_middle::dep_graph::WorkProduct; -use rustc_middle::lint::LevelSpec; +use rustc_middle::lint::StableLevelSpec; use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile; use rustc_middle::middle::dependency_format::Dependencies; use rustc_middle::middle::exported_symbols::SymbolExportKind; @@ -342,8 +342,8 @@ impl CompiledModules { /// Instead, encode exactly the information we need. #[derive(Copy, Clone, Debug, Encodable, Decodable)] pub struct CodegenLintLevelSpecs { - linker_messages: LevelSpec, - linker_info: LevelSpec, + linker_messages: StableLevelSpec, + linker_info: StableLevelSpec, } impl CodegenLintLevelSpecs { diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 0feb22e8d1d70..90ac8c89ba9ad 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -454,13 +454,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { OperandValue::Pair(lldata, llextra) } mir::CastKind::PointerCoercion( - PointerCoercion::MutToConstPointer | PointerCoercion::ArrayToPointer, _ + PointerCoercion::MutToConstPointer | PointerCoercion::ArrayToPointer, + _, ) => { bug!("{kind:?} is for borrowck, and should never appear in codegen"); } - mir::CastKind::PtrToPtr - if bx.cx().is_backend_scalar_pair(operand.layout) => - { + mir::CastKind::PtrToPtr if bx.cx().is_backend_scalar_pair(operand.layout) => { if let OperandValue::Pair(data_ptr, meta) = operand.val { if bx.cx().is_backend_scalar_pair(cast) { OperandValue::Pair(data_ptr, meta) @@ -483,7 +482,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // path as the other integer-to-X casts. | mir::CastKind::PointerWithExposedProvenance => { let imm = operand.immediate(); - let abi::BackendRepr::Scalar(from_scalar) = operand.layout.backend_repr else { + let abi::BackendRepr::Scalar(from_scalar) = operand.layout.backend_repr + else { bug!("Found non-scalar for operand {operand:?}"); }; let from_backend_ty = bx.cx().immediate_backend_type(operand.layout); @@ -498,11 +498,18 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bug!("Found non-scalar for cast {cast:?}"); }; - self.cast_immediate(bx, imm, from_scalar, from_backend_ty, to_scalar, to_backend_ty) - .map(OperandValue::Immediate) - .unwrap_or_else(|| { - bug!("Unsupported cast of {operand:?} to {cast:?}"); - }) + self.cast_immediate( + bx, + imm, + from_scalar, + from_backend_ty, + to_scalar, + to_backend_ty, + ) + .map(OperandValue::Immediate) + .unwrap_or_else(|| { + bug!("Unsupported cast of {operand:?} to {cast:?}"); + }) } mir::CastKind::Transmute | mir::CastKind::Subtype => { self.codegen_transmute_operand(bx, operand, cast) @@ -553,6 +560,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { move_annotation: None, } } + mir::Rvalue::BinaryOp(op, (ref lhs, ref rhs)) => { let lhs = self.codegen_operand(bx, lhs); let rhs = self.codegen_operand(bx, rhs); @@ -666,7 +674,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }; OperandRef { val: OperandValue::Immediate(static_), layout, move_annotation: None } } + mir::Rvalue::Use(ref operand, _) => self.codegen_operand(bx, operand), + mir::Rvalue::Repeat(ref elem, len_const) => { // All arrays have `BackendRepr::Memory`, so only the ZST cases // end up here. Anything else forces the destination local to be @@ -682,6 +692,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { move_annotation: None, } } + mir::Rvalue::Aggregate(ref kind, ref fields) => { let (variant_index, active_field_index) = match **kind { mir::AggregateKind::Adt(_, variant_index, _, _, active_field_index) => { @@ -719,12 +730,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } } + mir::Rvalue::WrapUnsafeBinder(ref operand, binder_ty) => { let operand = self.codegen_operand(bx, operand); let binder_ty = self.monomorphize(binder_ty); let layout = bx.cx().layout_of(binder_ty); OperandRef { val: operand.val, layout, move_annotation: None } } + mir::Rvalue::CopyForDeref(_) => bug!("`CopyForDeref` in codegen"), } } diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs index 1d19ce49f2b93..1e65496926e84 100644 --- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs +++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs @@ -109,8 +109,7 @@ fn const_to_valtree_inner<'tcx>( // switch to the base type. place.layout = ecx.layout_of(*base).unwrap(); ensure_sufficient_stack(|| const_to_valtree_inner(ecx, &place, num_nodes)) - }, - + } ty::RawPtr(_, _) => { // Not all raw pointers are allowed, as we cannot properly test them for @@ -137,23 +136,19 @@ fn const_to_valtree_inner<'tcx>( // agree with runtime equality tests. ty::FnPtr(..) => Err(ValTreeCreationError::NonSupportedType(ty)), - ty::Ref(_, _, _) => { + ty::Ref(_, _, _) => { let derefd_place = ecx.deref_pointer(place).report_err()?; const_to_valtree_inner(ecx, &derefd_place, num_nodes) } - ty::Str | ty::Slice(_) | ty::Array(_, _) => { - slice_branches(ecx, place, num_nodes) - } + ty::Str | ty::Slice(_) | ty::Array(_, _) => slice_branches(ecx, place, num_nodes), // Trait objects are not allowed in type level constants, as we have no concept for // resolving their backing type, even if we can do that at const eval time. We may // hypothetically be able to allow `dyn StructuralPartialEq` trait objects in the future, // but it is unclear if this is useful. ty::Dynamic(..) => Err(ValTreeCreationError::NonSupportedType(ty)), - ty::Tuple(elem_tys) => { - branches(ecx, place, elem_tys.len(), None, num_nodes) - } + ty::Tuple(elem_tys) => branches(ecx, place, elem_tys.len(), None, num_nodes), ty::Adt(def, _) => { if def.is_union() { @@ -163,22 +158,30 @@ fn const_to_valtree_inner<'tcx>( } let variant = ecx.read_discriminant(place).report_err()?; - branches(ecx, place, def.variant(variant).fields.len(), def.is_enum().then_some(variant), num_nodes) + branches( + ecx, + place, + def.variant(variant).fields.len(), + def.is_enum().then_some(variant), + num_nodes, + ) } + // FIXME(oli-obk): we could look behind opaque types + ty::Alias(..) => Err(ValTreeCreationError::NonSupportedType(ty)), + + // FIXME(oli-obk): we can probably encode closures just like structs + ty::Closure(..) => Err(ValTreeCreationError::NonSupportedType(ty)), + ty::Never | ty::Error(_) | ty::Foreign(..) | ty::Infer(ty::FreshIntTy(_)) | ty::Infer(ty::FreshFloatTy(_)) - // FIXME(oli-obk): we could look behind opaque types - | ty::Alias(..) | ty::Param(_) | ty::Bound(..) | ty::Placeholder(..) | ty::Infer(_) - // FIXME(oli-obk): we can probably encode closures just like structs - | ty::Closure(..) | ty::CoroutineClosure(..) | ty::Coroutine(..) | ty::CoroutineWitness(..) diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 31353d1eac0fb..7f9f83b5c963d 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -213,7 +213,6 @@ pub fn run_compiler(at_args: &[String], callbacks: &mut (dyn Callbacks + Send)) output_dir: odir, ice_file, file_loader: None, - lint_caps: Default::default(), psess_created: None, track_state: None, register_lints: None, diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 35d0188769f51..0569c1b986d1a 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2558,12 +2558,10 @@ impl Expr<'_> { }; match &self.kind { - ExprKind::Closure(closure) => { - match closure.fn_decl.output { - FnRetTy::DefaultReturn(_) => ExprPrecedence::Jump, - FnRetTy::Return(_) => prefix_attrs_precedence(), - } - } + ExprKind::Closure(closure) => match closure.fn_decl.output { + FnRetTy::DefaultReturn(_) => ExprPrecedence::Jump, + FnRetTy::Return(_) => prefix_attrs_precedence(), + }, ExprKind::Break(..) | ExprKind::Ret(..) @@ -2574,17 +2572,16 @@ impl Expr<'_> { ExprKind::Binary(op, ..) => op.node.precedence(), ExprKind::Cast(..) => ExprPrecedence::Cast, - ExprKind::Assign(..) | - ExprKind::AssignOp(..) => ExprPrecedence::Assign, + ExprKind::Assign(..) | ExprKind::AssignOp(..) => ExprPrecedence::Assign, // Unary, prefix - ExprKind::AddrOf(..) + ExprKind::AddrOf(..) => ExprPrecedence::Prefix, + // Here `let pats = expr` has `let pats =` as a "unary" prefix of `expr`. // However, this is not exactly right. When `let _ = a` is the LHS of a binop we // need parens sometimes. E.g. we can print `(let _ = a) && b` as `let _ = a && b` // but we need to print `(let _ = a) < b` as-is with parens. - | ExprKind::Let(..) - | ExprKind::Unary(..) => ExprPrecedence::Prefix, + ExprKind::Let(..) | ExprKind::Unary(..) => ExprPrecedence::Prefix, // Need parens if and only if there are prefix attributes. ExprKind::Array(_) diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 5454b282d5226..6e4d6aa80a63a 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -40,6 +40,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { || self.suggest_semicolon_in_repeat_expr(err, expr, expr_ty) || self.suggest_deref_ref_or_into(err, expr, expected, expr_ty, expected_ty_expr) || self.suggest_option_to_bool(err, expr, expr_ty, expected) + || self.suggest_collect(err, expr, expected, expr_ty) || self.suggest_compatible_variants(err, expr, expected, expr_ty) || self.suggest_non_zero_new_unwrap(err, expr, expected, expr_ty) || self.suggest_calling_boxed_future_when_appropriate(err, expr, expected, expr_ty) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 955ce5a6b58b5..323f0fb040d6b 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -250,6 +250,74 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + /// Suggests calling `.collect()` on an `Iterator` it can be collected in the return type + /// ```compile_fail + /// let x: String = "foo".chars().map(|c| c); // with a .collect() here the code compiles + /// ``` + pub(crate) fn suggest_collect( + &self, + err: &mut Diag<'_>, + expr: &hir::Expr<'_>, + expected_type: Ty<'tcx>, + found_type: Ty<'tcx>, + ) -> bool { + let tcx = self.tcx; + let expected = self.resolve_vars_if_possible(expected_type); + let found = self.resolve_vars_if_possible(found_type); + + if expected.references_error() || found.references_error() || expected.is_unit() { + return false; + } + + let Some(iterator_trait_id) = tcx.get_diagnostic_item(sym::Iterator) else { + return false; + }; + + if !self + .infcx + .type_implements_trait(iterator_trait_id, [found], self.param_env) + .must_apply_modulo_regions() + { + return false; + } + + let Some(from_iterator_trait_id) = tcx.get_diagnostic_item(sym::FromIterator) else { + return false; + }; + + let Some(iterator_item_id) = tcx + .associated_items(iterator_trait_id) + .in_definition_order() + .find(|item| item.name() == sym::Item) + .map(|item| item.def_id) + else { + return false; + }; + + let item_type = Ty::new_projection(tcx, iterator_item_id, [found]); + let item_type = + self.normalize(expr.span, rustc_middle::ty::Unnormalized::new_wip(item_type)); + + let can_collect = self + .infcx + .type_implements_trait(from_iterator_trait_id, [expected, item_type], self.param_env) + .may_apply(); + + if can_collect { + err.span_suggestion_verbose( + expr.span.shrink_to_hi(), + format!( + "consider using `.collect()` to convert the `Iterator` into a `{expected}`" + ), + ".collect()", + rustc_errors::Applicability::MaybeIncorrect, + ); + return true; + } + + false + } + pub(crate) fn suggest_remove_last_method_call( &self, err: &mut Diag<'_>, diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 7bebe72971a9e..c9ec32159f476 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -1903,10 +1903,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (FxIndexSet::default(), FxIndexSet::default(), Vec::new()) }); entry.0.insert(cause_span); - entry.1.insert(( - cause_span, - cause_msg, - )); + entry.1.insert((cause_span, cause_msg)); entry.2.push(p); skip_list.insert(p); manually_impl = true; @@ -1918,16 +1915,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span: item_span, .. })) => { - let sized_pred = - unsatisfied_predicates.iter().any(|(pred, _, _)| { - match pred.kind().skip_binder() { - ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => { - self.tcx.is_lang_item(pred.def_id(), LangItem::Sized) - && pred.polarity == ty::PredicatePolarity::Positive - } - _ => false, + let sized_pred = unsatisfied_predicates.iter().any(|(pred, _, _)| { + match pred.kind().skip_binder() { + ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => { + self.tcx.is_lang_item(pred.def_id(), LangItem::Sized) + && pred.polarity == ty::PredicatePolarity::Positive } - }); + _ => false, + } + }); for param in generics.params { if param.span == cause_span && sized_pred { let (sp, sugg) = match param.colon_span { @@ -1954,7 +1950,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { entry.2.push(p); if cause_span != *item_span { entry.0.insert(cause_span); - entry.1.insert((cause_span, "unsatisfied trait bound introduced here".to_string())); + entry.1.insert(( + cause_span, + "unsatisfied trait bound introduced here".to_string(), + )); } else { if let Some(of_trait) = of_trait { entry.0.insert(of_trait.trait_ref.path.span); @@ -1967,7 +1966,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { entry.1.insert((self_ty.span, String::new())); } Some(Node::Item(hir::Item { - kind: hir::ItemKind::Trait { is_auto: rustc_ast::ast::IsAuto::Yes, .. }, + kind: hir::ItemKind::Trait { is_auto: rustc_ast::ast::IsAuto::Yes, .. }, span: item_span, .. })) => { @@ -1994,7 +1993,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }); entry.0.insert(cause_span); entry.1.insert((ident.span, String::new())); - entry.1.insert((cause_span, "unsatisfied trait bound introduced here".to_string())); + entry.1.insert(( + cause_span, + "unsatisfied trait bound introduced here".to_string(), + )); entry.2.push(p); } _ => { diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 875ed4ae5d307..2b90606c83f29 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -4,7 +4,7 @@ use std::sync::Arc; use rustc_ast::{LitKind, MetaItemKind, token}; use rustc_codegen_ssa::traits::CodegenBackend; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::jobserver::{self, Proxy}; use rustc_errors::{DiagCtxtHandle, ErrorGuaranteed}; use rustc_lint::LintStore; @@ -18,7 +18,7 @@ use rustc_parse::parser::attr::AllowLeadingUnsafe; use rustc_query_impl::print_query_stack; use rustc_session::config::{self, Cfg, CheckCfg, ExpectedValues, Input, OutFileName}; use rustc_session::parse::ParseSess; -use rustc_session::{CompilerIO, EarlyDiagCtxt, Session, lint}; +use rustc_session::{CompilerIO, EarlyDiagCtxt, Session}; use rustc_span::source_map::{FileLoader, RealFileLoader, SourceMapInputs}; use rustc_span::{FileName, sym}; use tracing::trace; @@ -330,8 +330,6 @@ pub struct Config { /// running rustc without having to save". (See #102759.) pub file_loader: Option>, - pub lint_caps: FxHashMap, - /// This is a callback from the driver that is called when [`ParseSess`] is created. pub psess_created: Option>, @@ -427,7 +425,6 @@ pub fn run_compiler(config: Config, f: impl FnOnce(&Compiler) -> R + Se output_file: config.output_file, temps_dir, }, - config.lint_caps, target, util::rustc_version_str().unwrap_or("unknown"), config.ice_file, diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 0837e7767605c..6788582e2c613 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -68,15 +68,7 @@ where static USING_INTERNAL_FEATURES: AtomicBool = AtomicBool::new(false); - let sess = build_session( - sessopts, - io, - Default::default(), - target, - "", - None, - &USING_INTERNAL_FEATURES, - ); + let sess = build_session(sessopts, io, target, "", None, &USING_INTERNAL_FEATURES); let cfg = parse_cfg(sess.dcx(), matches.opt_strs("cfg")); let cfg = build_configuration(&sess, cfg); f(sess, cfg) diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 672bbdece2861..2c7ccfb25ae9b 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -1508,8 +1508,7 @@ impl<'tcx> LateLintPass<'tcx> for TrivialConstraints { for &(predicate, span) in predicates.predicates { let predicate_kind_name = match predicate.kind().skip_binder() { ClauseKind::Trait(..) => "trait", - ClauseKind::TypeOutlives(..) | - ClauseKind::RegionOutlives(..) => "lifetime", + ClauseKind::TypeOutlives(..) | ClauseKind::RegionOutlives(..) => "lifetime", ClauseKind::UnstableFeature(_) // `ConstArgHasType` is never global as `ct` is always a param diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 4825b61bc6e41..3cbd02e2ed8d9 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -20,14 +20,17 @@ use rustc_hir::def_id::{CrateNum, DefId}; use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData}; use rustc_hir::{Pat, PatKind}; use rustc_middle::bug; -use rustc_middle::lint::LevelSpec; +use rustc_middle::lint::{LevelSpec, StableLevelSpec, UnstableLevelSpec}; use rustc_middle::middle::privacy::EffectiveVisibilities; use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout}; use rustc_middle::ty::print::{PrintError, PrintTraitRefExt as _, Printer, with_no_trimmed_paths}; use rustc_middle::ty::{ self, GenericArg, RegisteredTools, Ty, TyCtxt, TypingEnv, TypingMode, Unnormalized, }; -use rustc_session::lint::{FutureIncompatibleInfo, Lint, LintExpectationId, LintId}; +use rustc_session::lint::{ + FutureIncompatibleInfo, Lint, LintExpectationId, LintId, StableLintExpectationId, + UnstableLintExpectationId, +}; use rustc_session::{DynLintStore, Session}; use rustc_span::edit_distance::find_best_match_for_names; use rustc_span::{Ident, Span, Symbol, sym}; @@ -510,6 +513,8 @@ pub struct EarlyContext<'a> { } pub trait LintContext { + type LintExpectationId: Copy + Into; + fn sess(&self) -> &Session; // FIXME: These methods should not take an Into -- instead, callers should need to @@ -538,7 +543,7 @@ pub trait LintContext { } /// This returns the lint level spec for the given lint at the current location. - fn get_lint_level_spec(&self, lint: &'static Lint) -> LevelSpec; + fn get_lint_level_spec(&self, lint: &'static Lint) -> LevelSpec; /// This function can be used to manually fulfill an expectation. This can /// be used for lints which contain several spans, and should be suppressed, @@ -547,7 +552,7 @@ pub trait LintContext { /// Note that this function should only be called for [`LintExpectationId`]s /// retrieved from the current lint pass. Buffered or manually created ids can /// cause ICEs. - fn fulfill_expectation(&self, expectation: LintExpectationId) { + fn fulfill_expectation(&self, expectation: Self::LintExpectationId) { // We need to make sure that submitted expectation ids are correctly fulfilled suppressed // and stored between compilation sessions. To not manually do these steps, we simply create // a dummy diagnostic and emit it as usual, which will be suppressed and stored like a @@ -556,7 +561,7 @@ pub trait LintContext { .dcx() .struct_expect( "this is a dummy diagnostic, to submit and store an expectation", - expectation, + expectation.into(), ) .emit(); } @@ -585,6 +590,8 @@ impl<'a> EarlyContext<'a> { } impl<'tcx> LintContext for LateContext<'tcx> { + type LintExpectationId = StableLintExpectationId; + /// Gets the overall compiler `Session` object. fn sess(&self) -> &Session { self.tcx.sess @@ -604,12 +611,14 @@ impl<'tcx> LintContext for LateContext<'tcx> { } } - fn get_lint_level_spec(&self, lint: &'static Lint) -> LevelSpec { + fn get_lint_level_spec(&self, lint: &'static Lint) -> StableLevelSpec { self.tcx.lint_level_spec_at_node(lint, self.last_node_with_lint_attrs) } } impl LintContext for EarlyContext<'_> { + type LintExpectationId = UnstableLintExpectationId; + /// Gets the overall compiler `Session` object. fn sess(&self) -> &Session { self.builder.sess() @@ -624,7 +633,7 @@ impl LintContext for EarlyContext<'_> { self.builder.opt_span_lint(lint, span.map(|s| s.into()), decorator) } - fn get_lint_level_spec(&self, lint: &'static Lint) -> LevelSpec { + fn get_lint_level_spec(&self, lint: &'static Lint) -> UnstableLevelSpec { self.builder.lint_level_spec(lint) } } diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index 903e223e97938..df6683c14df42 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -53,7 +53,7 @@ impl<'ecx, T: EarlyLintPass> EarlyContextAndPass<'ecx, T> { { let is_crate_node = id == ast::CRATE_NODE_ID; debug!(?id); - let push = self.context.builder.push(attrs, is_crate_node, None); + let push = self.context.builder.push(attrs, is_crate_node); debug!("early context: enter_attrs({:?})", attrs); lint_callback!(self, check_attributes, attrs); diff --git a/compiler/rustc_lint/src/expect.rs b/compiler/rustc_lint/src/expect.rs index 481e116d06e01..5364a4141805b 100644 --- a/compiler/rustc_lint/src/expect.rs +++ b/compiler/rustc_lint/src/expect.rs @@ -2,8 +2,8 @@ use rustc_data_structures::fx::FxHashSet; use rustc_middle::lint::LintExpectation; use rustc_middle::query::Providers; use rustc_middle::ty::TyCtxt; -use rustc_session::lint::LintExpectationId; use rustc_session::lint::builtin::UNFULFILLED_LINT_EXPECTATIONS; +use rustc_session::lint::{LintExpectationId, StableLintExpectationId}; use rustc_span::Symbol; use crate::lints::{Expectation, ExpectationNote}; @@ -12,7 +12,7 @@ pub(crate) fn provide(providers: &mut Providers) { *providers = Providers { lint_expectations, check_expectations, ..*providers }; } -fn lint_expectations(tcx: TyCtxt<'_>, (): ()) -> Vec<(LintExpectationId, LintExpectation)> { +fn lint_expectations(tcx: TyCtxt<'_>, (): ()) -> Vec<(StableLintExpectationId, LintExpectation)> { let krate = tcx.hir_crate_items(()); let mut expectations = Vec::new(); @@ -31,30 +31,22 @@ fn check_expectations(tcx: TyCtxt<'_>, tool_filter: Option) { // Turn a `LintExpectationId` into a `(AttrId, lint_index)` pair. let canonicalize_id = |expect_id: &LintExpectationId| { - match *expect_id { - LintExpectationId::Unstable { attr_id, lint_index: Some(lint_index) } => { - (attr_id, lint_index) - } - LintExpectationId::Stable { hir_id, attr_index, lint_index: Some(lint_index) } => { + let (attr_id, lint_index) = match *expect_id { + LintExpectationId::Unstable(id) => (id.attr_id, id.lint_index), + LintExpectationId::Stable(id) => { // We are an `eval_always` query, so looking at the attribute's `AttrId` is ok. - let attr_id = tcx.hir_attrs(hir_id)[attr_index as usize].id(); - - (attr_id, lint_index) + (tcx.hir_attrs(id.hir_id)[id.attr_index as usize].id(), id.lint_index) } - _ => panic!("fulfilled expectations must have a lint index"), - } + }; + (attr_id, lint_index.expect("fulfilled expectations must have a lint index")) }; let fulfilled_expectations: FxHashSet<_> = fulfilled_expectations.iter().map(canonicalize_id).collect(); for (expect_id, expectation) in lint_expectations { - // This check will always be true, since `lint_expectations` only holds stable ids - let LintExpectationId::Stable { hir_id, .. } = expect_id else { - unreachable!("at this stage all `LintExpectationId`s are stable"); - }; - - let expect_id = canonicalize_id(expect_id); + let hir_id = expect_id.hir_id; + let expect_id = canonicalize_id(&LintExpectationId::Stable(*expect_id)); if !fulfilled_expectations.contains(&expect_id) && tool_filter.is_none_or(|filter| expectation.lint_tool == Some(filter)) @@ -63,7 +55,7 @@ fn check_expectations(tcx: TyCtxt<'_>, tool_filter: Option) { let note = expectation.is_unfulfilled_lint_expectations; tcx.emit_node_span_lint( UNFULFILLED_LINT_EXPECTATIONS, - *hir_id, + hir_id, expectation.emission_span, Expectation { rationale, note }, ); diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs index 3cc0d46d8541f..0a074c6652a1d 100644 --- a/compiler/rustc_lint/src/late.rs +++ b/compiler/rustc_lint/src/late.rs @@ -439,14 +439,6 @@ fn late_lint_crate<'tcx>(tcx: TyCtxt<'tcx>) { filtered_passes.push(Box::new(HardwiredLints)); let pass = RuntimeCombinedLateLintPass { passes: &mut filtered_passes[..] }; - late_lint_crate_inner(tcx, context, pass); -} - -fn late_lint_crate_inner<'tcx, T: LateLintPass<'tcx>>( - tcx: TyCtxt<'tcx>, - context: LateContext<'tcx>, - pass: T, -) { let mut cx = LateContextAndPass { context, pass }; // Visit the whole crate. diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index ad74b0ee906a1..b8da46594cfc2 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -1,3 +1,5 @@ +use std::fmt::Debug; + use rustc_ast as ast; use rustc_ast::attr::AttributeExt; use rustc_ast_pretty::pprust; @@ -11,8 +13,8 @@ use rustc_hir::intravisit::{self, Visitor}; use rustc_index::IndexVec; use rustc_middle::hir::nested_filter; use rustc_middle::lint::{ - LevelSpec, LintExpectation, LintLevelSource, ShallowLintLevelMap, emit_lint_base, - reveal_actual_level_spec, + LevelSpec, LintExpectation, LintLevelSource, ShallowLintLevelMap, StableLevelSpec, + UnstableLevelSpec, emit_lint_base, reveal_actual_level_spec, }; use rustc_middle::query::Providers; use rustc_middle::ty::{RegisteredTools, TyCtxt}; @@ -21,8 +23,10 @@ use rustc_session::lint::builtin::{ self, FORBIDDEN_LINT_GROUPS, RENAMED_AND_REMOVED_LINTS, SINGLE_USE_LIFETIMES, UNFULFILLED_LINT_EXPECTATIONS, UNKNOWN_LINTS, UNUSED_ATTRIBUTES, }; -use rustc_session::lint::{Level, Lint, LintExpectationId, LintId}; -use rustc_span::{DUMMY_SP, Span, Symbol, sym}; +use rustc_session::lint::{ + Level, Lint, LintExpectationId, LintId, StableLintExpectationId, UnstableLintExpectationId, +}; +use rustc_span::{AttrId, DUMMY_SP, Span, Symbol, sym}; use tracing::{debug, instrument}; use crate::builtin::MISSING_DOCS; @@ -64,9 +68,7 @@ rustc_index::newtype_index! { /// to find the specifications for a given lint. #[derive(Debug)] struct LintSet { - // -A,-W,-D flags, a `Symbol` for the flag itself and `LevelSpec` for which - // flag. - specs: FxIndexMap, + specs: FxIndexMap, parent: LintStackIndex, } @@ -79,9 +81,9 @@ impl LintLevelSets { &self, lint: &'static Lint, idx: LintStackIndex, - aux: Option<&FxIndexMap>, + aux: Option<&FxIndexMap>, sess: &Session, - ) -> LevelSpec { + ) -> UnstableLevelSpec { reveal_actual_level_spec(sess, LintId::of(lint), |id| { self.raw_lint_level_spec(id, idx, aux) }) @@ -91,8 +93,8 @@ impl LintLevelSets { &self, id: LintId, mut idx: LintStackIndex, - aux: Option<&FxIndexMap>, - ) -> Option { + aux: Option<&FxIndexMap>, + ) -> Option { if let Some(specs) = aux && let Some(level_spec) = specs.get(&id) { @@ -213,26 +215,53 @@ pub struct TopDown { } pub trait LintLevelsProvider { - fn current_specs(&self) -> &FxIndexMap; - fn insert(&mut self, id: LintId, level_spec: LevelSpec); - fn get_lint_level_spec(&self, lint: &'static Lint, sess: &Session) -> LevelSpec; - fn push_expectation(&mut self, id: LintExpectationId, expectation: LintExpectation); + type LintExpectationId: Copy + Debug + Into; + + fn current_specs(&self) -> &FxIndexMap>; + + fn insert(&mut self, id: LintId, level_spec: LevelSpec); + + fn get_lint_level_spec( + &self, + lint: &'static Lint, + sess: &Session, + ) -> LevelSpec; + + fn push_expectation(&mut self, id: Self::LintExpectationId, expectation: LintExpectation); + + fn mk_lint_expectation_id( + &self, + attr_id: AttrId, + attr_index: usize, + lint_index: Option, + ) -> Self::LintExpectationId; } impl LintLevelsProvider for TopDown { - fn current_specs(&self) -> &FxIndexMap { + type LintExpectationId = UnstableLintExpectationId; + + fn current_specs(&self) -> &FxIndexMap { &self.sets.list[self.cur].specs } - fn insert(&mut self, id: LintId, level_spec: LevelSpec) { + fn insert(&mut self, id: LintId, level_spec: UnstableLevelSpec) { self.sets.list[self.cur].specs.insert(id, level_spec); } - fn get_lint_level_spec(&self, lint: &'static Lint, sess: &Session) -> LevelSpec { + fn get_lint_level_spec(&self, lint: &'static Lint, sess: &Session) -> UnstableLevelSpec { self.sets.get_lint_level_spec(lint, self.cur, Some(self.current_specs()), sess) } - fn push_expectation(&mut self, _: LintExpectationId, _: LintExpectation) {} + fn push_expectation(&mut self, _: Self::LintExpectationId, _: LintExpectation) {} + + fn mk_lint_expectation_id( + &self, + attr_id: AttrId, + _attr_index: usize, + lint_index: Option, + ) -> Self::LintExpectationId { + UnstableLintExpectationId { attr_id, lint_index } + } } struct LintLevelQueryMap<'tcx> { @@ -240,33 +269,44 @@ struct LintLevelQueryMap<'tcx> { cur: HirId, specs: ShallowLintLevelMap, /// Empty hash map to simplify code. - empty: FxIndexMap, + empty: FxIndexMap, attrs: &'tcx hir::AttributeMap<'tcx>, } impl LintLevelsProvider for LintLevelQueryMap<'_> { - fn current_specs(&self) -> &FxIndexMap { + type LintExpectationId = StableLintExpectationId; + + fn current_specs(&self) -> &FxIndexMap { self.specs.specs.get(&self.cur.local_id).unwrap_or(&self.empty) } - fn insert(&mut self, id: LintId, level_spec: LevelSpec) { + + fn insert(&mut self, id: LintId, level_spec: StableLevelSpec) { self.specs.specs.get_mut_or_insert_default(self.cur.local_id).insert(id, level_spec); } - fn get_lint_level_spec(&self, lint: &'static Lint, _: &Session) -> LevelSpec { + + fn get_lint_level_spec(&self, lint: &'static Lint, _: &Session) -> StableLevelSpec { self.specs.lint_level_spec_at_node(self.tcx, LintId::of(lint), self.cur) } - fn push_expectation(&mut self, id: LintExpectationId, expectation: LintExpectation) { + + fn push_expectation(&mut self, id: Self::LintExpectationId, expectation: LintExpectation) { self.specs.expectations.push((id, expectation)) } + + fn mk_lint_expectation_id( + &self, + _attr_id: AttrId, + attr_index: usize, + lint_index: Option, + ) -> Self::LintExpectationId { + let attr_index = attr_index.try_into().unwrap(); + StableLintExpectationId { hir_id: self.cur, attr_index, lint_index } + } } impl<'tcx> LintLevelsBuilder<'_, LintLevelQueryMap<'tcx>> { fn add_id(&mut self, hir_id: HirId) { self.provider.cur = hir_id; - self.add( - self.provider.attrs.get(hir_id.local_id), - hir_id == hir::CRATE_HIR_ID, - Some(hir_id), - ); + self.add(self.provider.attrs.get(hir_id.local_id), hir_id == hir::CRATE_HIR_ID); } } @@ -386,7 +426,7 @@ impl<'s> LintLevelsBuilder<'s, TopDown> { crate_attrs: &[ast::Attribute], ) -> Self { let mut builder = Self::new(sess, features, lint_added_lints, store, registered_tools); - builder.add(crate_attrs, true, None); + builder.add(crate_attrs, true); builder } @@ -413,17 +453,12 @@ impl<'s> LintLevelsBuilder<'s, TopDown> { /// `#[allow]` /// /// Don't forget to call `pop`! - pub(crate) fn push( - &mut self, - attrs: &[ast::Attribute], - is_crate_node: bool, - source_hir_id: Option, - ) -> BuilderPush { + pub(crate) fn push(&mut self, attrs: &[ast::Attribute], is_crate_node: bool) -> BuilderPush { let prev = self.provider.cur; self.provider.cur = self.provider.sets.list.push(LintSet { specs: FxIndexMap::default(), parent: prev }); - self.add(attrs, is_crate_node, source_hir_id); + self.add(attrs, is_crate_node); if self.provider.current_specs().is_empty() { self.provider.sets.list.pop(); @@ -447,7 +482,10 @@ impl Drop for BuilderPush { } } -impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { +impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> +where + LevelSpec: Into, +{ pub(crate) fn sess(&self) -> &Session { self.sess } @@ -456,14 +494,6 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { self.features } - fn current_specs(&self) -> &FxIndexMap { - self.provider.current_specs() - } - - fn insert(&mut self, id: LintId, level_spec: LevelSpec) { - self.provider.insert(id, level_spec) - } - fn add_command_line(&mut self) { for &(ref lint_name, level) in &self.sess.opts.lint_opts { // Checks the validity of lint names derived from the command line. @@ -520,7 +550,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { }; for &id in ids { // ForceWarn and Forbid cannot be overridden - if let Some(level_spec) = self.current_specs().get(&id) + if let Some(level_spec) = self.provider.current_specs().get(&id) && matches!(level_spec.level(), Level::ForceWarn | Level::Forbid) { continue; @@ -528,7 +558,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { if self.check_gated_lint(id, DUMMY_SP, true) { let src = LintLevelSource::CommandLine(lint_flag_val, level); - self.insert(id, LevelSpec::new(level, None, src)); + self.provider.insert(id, LevelSpec::new(level, None, src)); } } } @@ -537,7 +567,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { /// Attempts to insert the `id` to `LevelSpec` map entry. If unsuccessful /// (e.g. if a forbid was already inserted on the same scope), then emits a /// diagnostic with no change to `specs`. - fn insert_spec(&mut self, id: LintId, level_spec: LevelSpec) { + fn insert_spec(&mut self, id: LintId, level_spec: LevelSpec) { let level = level_spec.level(); let lint_id = level_spec.lint_id(); let src = level_spec.src; @@ -562,7 +592,6 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { // as preventing `allow(lint)` for some lint `lint` in // `lint_group`. For now, issue a future-compatibility // warning for this case. - let id_name = id.lint.name_lower(); let fcw_warning = match old_src { LintLevelSource::Default => false, LintLevelSource::Node { name, .. } => self.store.is_lint_group(name), @@ -571,9 +600,9 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { debug!( "fcw_warning={:?}, specs.get(&id) = {:?}, old_src={:?}, id_name={:?}", fcw_warning, - self.current_specs(), + self.provider.current_specs(), old_src, - id_name + id.lint.name_lower(), ); let sub = match old_src { LintLevelSource::Default => { @@ -627,27 +656,22 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { match (old_level, level) { // If the new level is an expectation store it in `ForceWarn` (Level::ForceWarn, Level::Expect) => { - self.insert(id, LevelSpec::new(Level::ForceWarn, lint_id, old_src)) + self.provider.insert(id, LevelSpec::new(Level::ForceWarn, lint_id, old_src)) } // Keep `ForceWarn` level but drop the expectation (Level::ForceWarn, _) => { - self.insert(id, LevelSpec::new(Level::ForceWarn, None, old_src)) + self.provider.insert(id, LevelSpec::new(Level::ForceWarn, None, old_src)) } // Set the lint level as normal - _ => self.insert(id, LevelSpec::new(level, lint_id, src)), + _ => self.provider.insert(id, LevelSpec::new(level, lint_id, src)), }; } - fn add( - &mut self, - attrs: &[impl AttributeExt], - is_crate_node: bool, - source_hir_id: Option, - ) { + fn add(&mut self, attrs: &[impl AttributeExt], is_crate_node: bool) { let sess = self.sess; for (attr_index, attr) in attrs.iter().enumerate() { if attr.is_automatically_derived_attr() { - self.insert( + self.provider.insert( LintId::of(SINGLE_USE_LIFETIMES), LevelSpec::new(Level::Allow, None, LintLevelSource::Default), ); @@ -656,30 +680,16 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { // `#[doc(hidden)]` disables missing_docs check. if attr.is_doc_hidden() { - self.insert( + self.provider.insert( LintId::of(MISSING_DOCS), LevelSpec::new(Level::Allow, None, LintLevelSource::Default), ); continue; } - let (level, lint_id) = match Level::from_opt_symbol(attr.name()) { + let level = match Level::from_opt_symbol(attr.name()) { None => continue, - // `Expect` is the only lint level with a `LintExpectationId` that can be created - // from an attribute. - Some(Level::Expect) => { - let id = if let Some(hir_id) = source_hir_id { - LintExpectationId::Stable { - hir_id, - attr_index: attr_index.try_into().unwrap(), - lint_index: None, - } - } else { - LintExpectationId::Unstable { attr_id: attr.id(), lint_index: None } - }; - (Level::Expect, Some(id)) - } - Some(level) => (level, None), + Some(level) => level, }; let Some(mut metas) = attr.meta_item_list() else { continue }; @@ -727,10 +737,15 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { } for (lint_index, li) in metas.iter_mut().enumerate() { - let mut lint_id = lint_id; - if let Some(id) = &mut lint_id { - id.set_lint_index(Some(lint_index as u16)); - } + // `Expect` is the only lint level with a `LintExpectationId` that can be created + // from an attribute. + let lint_id = (level == Level::Expect).then(|| { + self.provider.mk_lint_expectation_id( + attr.id(), + attr_index, + Some(lint_index as u16), + ) + }); let sp = li.span(); let meta_item = match li { @@ -902,7 +917,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { } if self.lint_added_lints && !is_crate_node { - for (id, level_spec) in self.current_specs().iter() { + for (id, level_spec) in self.provider.current_specs().iter() { if !id.lint.crate_level_only { continue; } @@ -988,7 +1003,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { } /// Find the lint level for a lint. - pub fn lint_level_spec(&self, lint: &'static Lint) -> LevelSpec { + pub fn lint_level_spec(&self, lint: &'static Lint) -> LevelSpec { self.provider.get_lint_level_spec(lint, self.sess) } diff --git a/compiler/rustc_lint/src/lifetime_syntax.rs b/compiler/rustc_lint/src/lifetime_syntax.rs index 6c65673acd0d8..1f3ecb03ebfc6 100644 --- a/compiler/rustc_lint/src/lifetime_syntax.rs +++ b/compiler/rustc_lint/src/lifetime_syntax.rs @@ -169,28 +169,19 @@ impl LifetimeSyntaxCategory { // E.g. `ContainsLifetime<'_>`. (ExplicitAnonymous, Path { .. }) | // E.g. `+ '_`, `+ use<'_>`. - (ExplicitAnonymous, OutlivesBound | PreciseCapturing) => { - Some(Self::Elided) - } + (ExplicitAnonymous, OutlivesBound | PreciseCapturing) => Some(Self::Elided), // E.g. `ContainsLifetime`. - (Implicit, Path { .. }) => { - Some(Self::Hidden) - } + (Implicit, Path { .. }) => Some(Self::Hidden), // E.g. `&'a T`. (ExplicitBound, Reference) | // E.g. `ContainsLifetime<'a>`. (ExplicitBound, Path { .. }) | // E.g. `+ 'a`, `+ use<'a>`. - (ExplicitBound, OutlivesBound | PreciseCapturing) => { - Some(Self::Named) - } + (ExplicitBound, OutlivesBound | PreciseCapturing) => Some(Self::Named), - (Implicit, OutlivesBound | PreciseCapturing) | - (_, Other) => { - None - } + (Implicit, OutlivesBound | PreciseCapturing) | (_, Other) => None, } } } diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 0cb7b4cce8462..ed7afa1c711de 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -761,23 +761,39 @@ impl EarlyLintPass for UnusedParens { let keep_space = (false, false); match &p.kind { // Do not lint on `(..)` as that will result in the other arms being useless. - Paren(_) + Paren(_) => {} // The other cases do not contain sub-patterns. - | Missing | Wild | Never | Rest | Expr(..) | MacCall(..) | Range(..) | Ident(.., None) - | Path(..) | Err(_) => {}, + Missing + | 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); - }, - Struct(_, _, fps, _) => for f in fps { - self.check_unused_parens_pat(cx, &f.pat, false, false, keep_space); - }, + TupleStruct(_, _, ps) | Tuple(ps) | Slice(ps) | Or(ps) => { + for p in ps { + self.check_unused_parens_pat(cx, p, false, false, keep_space); + } + } + Struct(_, _, fps, _) => { + for f in fps { + self.check_unused_parens_pat(cx, &f.pat, false, false, keep_space); + } + } // Avoid linting on `i @ (p0 | .. | pn)` and `box (p0 | .. | pn)`, #64106. - Ident(.., Some(p)) | Box(p) | Deref(p) | Guard(p, _) => self.check_unused_parens_pat(cx, p, true, false, keep_space), + Ident(.., Some(p)) | Box(p) | Deref(p) | Guard(p, _) => { + self.check_unused_parens_pat(cx, p, true, false, keep_space) + } // Avoid linting on `&(mut x)` as `&mut x` has a different meaning, #55342. // Also avoid linting on `& mut? (p0 | .. | pn)`, #64106. // FIXME(pin_ergonomics): check pinned patterns - Ref(p, _, m) => self.check_unused_parens_pat(cx, p, true, *m == Mutability::Not, keep_space), + Ref(p, _, m) => { + self.check_unused_parens_pat(cx, p, true, *m == Mutability::Not, keep_space) + } } } diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 2e690c7185f8c..fc8b2b65a8d48 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -100,47 +100,48 @@ pub enum Applicability { /// have that amount of lints listed. `u16` values should therefore suffice. #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Encodable, Decodable)] pub enum LintExpectationId { - /// Used for lints emitted during the `EarlyLintPass`. This id is not - /// hash stable and should not be cached. - Unstable { attr_id: AttrId, lint_index: Option }, - /// The [`HirId`] that the lint expectation is attached to. This id is - /// stable and can be cached. The additional index ensures that nodes with - /// several expectations can correctly match diagnostics to the individual - /// expectation. - Stable { hir_id: HirId, attr_index: u16, lint_index: Option }, -} - -impl LintExpectationId { - pub fn is_stable(&self) -> bool { - match self { - LintExpectationId::Unstable { .. } => false, - LintExpectationId::Stable { .. } => true, - } - } + Unstable(UnstableLintExpectationId), + Stable(StableLintExpectationId), +} - pub fn set_lint_index(&mut self, new_lint_index: Option) { - let (LintExpectationId::Unstable { lint_index, .. } - | LintExpectationId::Stable { lint_index, .. }) = self; +/// Used for lints emitted during the `EarlyLintPass`. This id is not hash +/// stable and should not be cached. +#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Encodable, Decodable)] +pub struct UnstableLintExpectationId { + pub attr_id: AttrId, + pub lint_index: Option, +} - *lint_index = new_lint_index +impl From for LintExpectationId { + fn from(id: UnstableLintExpectationId) -> LintExpectationId { + LintExpectationId::Unstable(id) } } -impl StableHash for LintExpectationId { +/// The [`HirId`] that the lint expectation is attached to. This id is stable +/// and can be cached. The additional index ensures that nodes with several +/// expectations can correctly match diagnostics to the individual expectation. +#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Encodable, Decodable)] +pub struct StableLintExpectationId { + pub hir_id: HirId, + pub attr_index: u16, + pub lint_index: Option, +} + +impl StableHash for StableLintExpectationId { #[inline] fn stable_hash(&self, hcx: &mut Hcx, hasher: &mut StableHasher) { - match self { - LintExpectationId::Stable { hir_id, attr_index, lint_index: Some(lint_index) } => { - hir_id.stable_hash(hcx, hasher); - attr_index.stable_hash(hcx, hasher); - lint_index.stable_hash(hcx, hasher); - } - _ => { - unreachable!( - "StableHash should only be called for filled and stable `LintExpectationId`" - ) - } - } + let StableLintExpectationId { hir_id, attr_index, lint_index } = self; + + hir_id.stable_hash(hcx, hasher); + attr_index.stable_hash(hcx, hasher); + lint_index.expect("must be filled to call `stable_hash`").stable_hash(hcx, hasher); + } +} + +impl From for LintExpectationId { + fn from(id: StableLintExpectationId) -> LintExpectationId { + LintExpectationId::Stable(id) } } diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index 41eeb1fc9811f..989013c6ff6fa 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -8,7 +8,8 @@ use rustc_lint_defs::EditionFcw; use rustc_macros::{Decodable, Encodable, StableHash}; use rustc_session::Session; use rustc_session::lint::{ - FutureIncompatibilityReason, Level, Lint, LintExpectationId, LintId, builtin, + FutureIncompatibilityReason, Level, Lint, LintExpectationId, LintId, StableLintExpectationId, + UnstableLintExpectationId, builtin, }; use rustc_span::{DUMMY_SP, ExpnKind, Span, Symbol, kw}; use tracing::instrument; @@ -55,7 +56,7 @@ impl LintLevelSource { /// Convenience helper for things that are frequently used together. #[derive(Copy, Clone, Debug, StableHash, Encodable, Decodable)] -pub struct LevelSpec { +pub struct LevelSpec { // This field *must* be private. It must be set in tandem with `lint_id`, only in // `LevelSpec::new`, because only certain `level`/`lint_id` combinations are valid. See // `LevelSpec::new` for those combinations. @@ -68,18 +69,17 @@ pub struct LevelSpec { level: Level, // This field *must* be private. See the comment on `level`. - lint_id: Option, + lint_id: Option, pub src: LintLevelSource, } -impl LevelSpec { +pub type UnstableLevelSpec = LevelSpec; +pub type StableLevelSpec = LevelSpec; + +impl LevelSpec { // Panics if an invalid `level`/`lint_id` combination is given. - pub fn new( - level: Level, - lint_id: Option, - src: LintLevelSource, - ) -> LevelSpec { + pub fn new(level: Level, lint_id: Option, src: LintLevelSource) -> LevelSpec { match (level, lint_id) { (Level::Allow | Level::Warn | Level::Deny | Level::Forbid, None) => {} (Level::Expect, Some(_)) => {} @@ -101,29 +101,48 @@ impl LevelSpec { self.level == Level::Expect } - pub fn lint_id(self) -> Option { + pub fn lint_id(self) -> Option { self.lint_id } } +impl From for LevelSpec { + fn from(level: UnstableLevelSpec) -> LevelSpec { + let LevelSpec { level, lint_id, src } = level; + let lint_id = lint_id.map(LintExpectationId::Unstable); + LevelSpec { level, lint_id, src } + } +} + +impl From for LevelSpec { + fn from(level: StableLevelSpec) -> LevelSpec { + let LevelSpec { level, lint_id, src } = level; + let lint_id = lint_id.map(LintExpectationId::Stable); + LevelSpec { level, lint_id, src } + } +} + /// Return type for the `shallow_lint_levels_on` query. /// -/// This map represents the set of allowed lints and allowance levels given -/// by the attributes for *a single HirId*. +/// This map represents lints levels given by the attributes for *a single HirId*. #[derive(Default, Debug, StableHash)] pub struct ShallowLintLevelMap { - pub expectations: Vec<(LintExpectationId, LintExpectation)>, - pub specs: SortedMap>, + // All the specs for this HirId. This is accessed frequently, e.g. for every lint emitted. + pub specs: SortedMap>, + + // Additional information about the `expect` specs for this HirId. This is consulted only once + // per compilation session, in `check_expectations`/`lint_expectations`. + pub expectations: Vec<(StableLintExpectationId, LintExpectation)>, } /// Verify the effect of special annotations: `warnings` lint level and lint caps. /// /// The return of this function is suitable for diagnostics. -pub fn reveal_actual_level_spec( +pub fn reveal_actual_level_spec( sess: &Session, lint: LintId, - probe_for_lint_level_spec: impl Fn(LintId) -> Option, -) -> LevelSpec { + probe_for_lint_level_spec: impl Fn(LintId) -> Option>, +) -> LevelSpec { let level_spec = probe_for_lint_level_spec(lint); // If `level` is none then we actually assume the default level for this lint. @@ -167,11 +186,6 @@ pub fn reveal_actual_level_spec( level_spec.level = min(level_spec.level, sess.opts.lint_cap.unwrap_or(Level::Forbid)); }; - // Ensure that we never exceed driver level. - if let Some(driver_level) = sess.driver_lint_caps.get(&lint) { - level_spec.level = min(level_spec.level, *driver_level); - } - level_spec } @@ -185,7 +199,7 @@ impl ShallowLintLevelMap { tcx: TyCtxt<'_>, id: LintId, start: HirId, - ) -> Option { + ) -> Option { if let Some(map) = self.specs.get(&start.local_id) && let Some(level_spec) = map.get(&id) { @@ -212,7 +226,12 @@ impl ShallowLintLevelMap { /// Fetch and return the user-visible lint level spec for the given lint at the given HirId. #[instrument(level = "trace", skip(self, tcx), ret)] - pub fn lint_level_spec_at_node(&self, tcx: TyCtxt<'_>, lint: LintId, cur: HirId) -> LevelSpec { + pub fn lint_level_spec_at_node( + &self, + tcx: TyCtxt<'_>, + lint: LintId, + cur: HirId, + ) -> StableLevelSpec { reveal_actual_level_spec(tcx.sess, lint, |lint| { self.probe_for_lint_level_spec(tcx, lint, cur) }) @@ -221,7 +240,7 @@ impl ShallowLintLevelMap { impl TyCtxt<'_> { /// Fetch and return the user-visible lint level spec for the given lint at the given HirId. - pub fn lint_level_spec_at_node(self, lint: &'static Lint, id: HirId) -> LevelSpec { + pub fn lint_level_spec_at_node(self, lint: &'static Lint, id: HirId) -> StableLevelSpec { self.shallow_lint_levels_on(id.owner).lint_level_spec_at_node(self, LintId::of(lint), id) } } @@ -362,7 +381,7 @@ fn explain_lint_level_source( pub fn emit_lint_base<'a, D: Diagnostic<'a, ()> + 'a>( sess: &'a Session, lint: &'static Lint, - level_spec: LevelSpec, + level_spec: impl Into, span: Option, decorate: D, ) { @@ -556,7 +575,7 @@ pub fn emit_lint_base<'a, D: Diagnostic<'a, ()> + 'a>( emit_lint_base_impl( sess, lint, - level_spec, + level_spec.into(), span, Box::new(move |dcx, level| decorate.into_diag(dcx, level)), ); diff --git a/compiler/rustc_middle/src/queries.rs b/compiler/rustc_middle/src/queries.rs index a9fc5dcac8f29..d62e4ec941d21 100644 --- a/compiler/rustc_middle/src/queries.rs +++ b/compiler/rustc_middle/src/queries.rs @@ -75,7 +75,7 @@ use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolMangli use rustc_session::cstore::{ CrateDepKind, CrateSource, ExternCrate, ForeignModule, LinkagePreference, NativeLib, }; -use rustc_session::lint::LintExpectationId; +use rustc_session::lint::StableLintExpectationId; use rustc_span::def_id::LOCAL_CRATE; use rustc_span::{DUMMY_SP, LocalExpnId, Span, Spanned, Symbol}; use rustc_target::spec::PanicStrategy; @@ -558,7 +558,7 @@ rustc_queries! { desc { "looking up lint levels for `{}`", tcx.def_path_str(key) } } - query lint_expectations(_: ()) -> &'tcx Vec<(LintExpectationId, LintExpectation)> { + query lint_expectations(_: ()) -> &'tcx Vec<(StableLintExpectationId, LintExpectation)> { arena_cache desc { "computing `#[expect]`ed lints in this crate" } } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 14bce52fefe63..9db9b1769ab9c 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1754,15 +1754,15 @@ impl<'tcx> Ty<'tcx> { | ty::Closure(..) | ty::CoroutineClosure(..) | ty::Never - | ty::Error(_) + | ty::Error(_) => Ok(tcx.types.unit), // Extern types have metadata = (). - | ty::Foreign(..) + ty::Foreign(..) => Ok(tcx.types.unit), // If returned by `struct_tail_raw` this is a unit struct // without any fields, or not a struct, and therefore is Sized. - | ty::Adt(..) + ty::Adt(..) => Ok(tcx.types.unit), // If returned by `struct_tail_raw` this is the empty tuple, // a.k.a. unit type, which is Sized - | ty::Tuple(..) => Ok(tcx.types.unit), + ty::Tuple(..) => Ok(tcx.types.unit), ty::Str | ty::Slice(_) => Ok(tcx.types.usize), @@ -1775,7 +1775,7 @@ impl<'tcx> Ty<'tcx> { // metadata of `tail`. ty::Param(_) | ty::Alias(..) => Err(tail), - | ty::UnsafeBinder(_) => todo!("FIXME(unsafe_binder)"), + ty::UnsafeBinder(_) => todo!("FIXME(unsafe_binder)"), ty::Infer(ty::TyVar(_)) | ty::Pat(..) diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs index 1386e6944e40f..d7e0a819d7ea1 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs @@ -450,12 +450,12 @@ impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> { match term.kind { TerminatorKind::Goto { target: _ } | TerminatorKind::FalseEdge { .. } - | TerminatorKind::FalseUnwind { .. } + | TerminatorKind::FalseUnwind { .. } => {} // In some sense returning moves the return place into the current // call's destination, however, since there are no statements after // this that could possibly access the return place, this doesn't // need recording. - | TerminatorKind::Return + TerminatorKind::Return | TerminatorKind::UnwindResume | TerminatorKind::UnwindTerminate(_) | TerminatorKind::CoroutineDrop @@ -510,8 +510,7 @@ impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> { } => { for op in operands { match *op { - InlineAsmOperand::In { reg: _, ref value } - => { + InlineAsmOperand::In { reg: _, ref value } => { self.gather_operand(value); } InlineAsmOperand::Out { reg: _, late: _, place, .. } => { diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index fcfdd7dcfa006..c7d18bd1cc92f 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -871,8 +871,9 @@ fn try_write_constant<'tcx>( ty::FnDef(..) => {} // Those are scalars, must be handled above. - ty::Bool | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Char => - throw_machine_stop_str!("primitive type with provenance"), + ty::Bool | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Char => { + throw_machine_stop_str!("primitive type with provenance") + } ty::Tuple(elem_tys) => { for (i, elem) in elem_tys.iter().enumerate() { @@ -898,7 +899,9 @@ fn try_write_constant<'tcx>( throw_machine_stop_str!("discriminant with provenance") }; let discr_bits = discr.to_bits(discr.size()); - let Some((variant, _)) = def.discriminants(*ecx.tcx).find(|(_, var)| discr_bits == var.val) else { + let Some((variant, _)) = + def.discriminants(*ecx.tcx).find(|(_, var)| discr_bits == var.val) + else { throw_machine_stop_str!("illegal discriminant for enum") }; let Some(variant_place) = map.apply(place, TrackElem::Variant(variant)) else { diff --git a/compiler/rustc_mir_transform/src/known_panics_lint.rs b/compiler/rustc_mir_transform/src/known_panics_lint.rs index 55167cddd4c8d..ff5006032308e 100644 --- a/compiler/rustc_mir_transform/src/known_panics_lint.rs +++ b/compiler/rustc_mir_transform/src/known_panics_lint.rs @@ -955,7 +955,9 @@ impl<'tcx> Visitor<'tcx> for CanConstProp { self.can_const_prop[local] = ConstPropMode::NoPropagation; } MutatingUse(MutatingUseContext::Projection) - | NonMutatingUse(NonMutatingUseContext::Projection) => bug!("visit_place should not pass {context:?} for {local:?}"), + | NonMutatingUse(NonMutatingUseContext::Projection) => { + bug!("visit_place should not pass {context:?} for {local:?}") + } } } } diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index 132dea85e4372..815b94dc510e8 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -145,26 +145,21 @@ impl<'a, 'tcx> CfgChecker<'a, 'tcx> { let src = self.body.basic_blocks.get(location.block).unwrap(); match (src.is_cleanup, bb.is_cleanup, edge_kind) { // Non-cleanup blocks can jump to non-cleanup blocks along non-unwind edges - (false, false, EdgeKind::Normal) + (false, false, EdgeKind::Normal) => {} // Cleanup blocks can jump to cleanup blocks along non-unwind edges - | (true, true, EdgeKind::Normal) => {} + (true, true, EdgeKind::Normal) => {} // Non-cleanup blocks can jump to cleanup blocks along unwind edges (false, true, EdgeKind::Unwind) => { self.unwind_edge_count += 1; } // All other jumps are invalid - _ => { - self.fail( - location, - format!( - "{:?} edge to {:?} violates unwind invariants (cleanup {:?} -> {:?})", - edge_kind, - bb, - src.is_cleanup, - bb.is_cleanup, - ) - ) - } + _ => self.fail( + location, + format!( + "{:?} edge to {:?} violates unwind invariants (cleanup {:?} -> {:?})", + edge_kind, bb, src.is_cleanup, bb.is_cleanup, + ), + ), } } else { self.fail(location, format!("encountered jump to invalid basic block {bb:?}")) diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 47ac91feefd4b..f935f43d336c8 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -1349,19 +1349,19 @@ impl<'a> Parser<'a> { (BinOpKind::Gt, AssocOp::Binary(BinOpKind::Gt | BinOpKind::Ge)) | (BinOpKind::Ge, AssocOp::Binary(BinOpKind::Gt | BinOpKind::Ge)) => { let expr_to_str = |e: &Expr| { - self.span_to_snippet(e.span) - .unwrap_or_else(|_| pprust::expr_to_string(e)) + self.span_to_snippet(e.span).unwrap_or_else(|_| pprust::expr_to_string(e)) }; - err.chaining_sugg = Some(ComparisonOperatorsCannotBeChainedSugg::SplitComparison { - span: inner_op.span.shrink_to_hi(), - middle_term: expr_to_str(r1), - }); + err.chaining_sugg = + Some(ComparisonOperatorsCannotBeChainedSugg::SplitComparison { + span: inner_op.span.shrink_to_hi(), + middle_term: expr_to_str(r1), + }); false // Keep the current parse behavior, where the AST is `(x < y) < z`. } // `x == y < z` ( BinOpKind::Eq, - AssocOp::Binary(BinOpKind::Lt | BinOpKind::Le | BinOpKind::Gt | BinOpKind::Ge) + AssocOp::Binary(BinOpKind::Lt | BinOpKind::Le | BinOpKind::Gt | BinOpKind::Ge), ) => { // Consume `z`/outer-op-rhs. let snapshot = self.create_snapshot_for_diagnostic(); @@ -1369,10 +1369,11 @@ impl<'a> Parser<'a> { Ok(r2) => { // We are sure that outer-op-rhs could be consumed, the suggestion is // likely correct. - err.chaining_sugg = Some(ComparisonOperatorsCannotBeChainedSugg::Parenthesize { - left: r1.span.shrink_to_lo(), - right: r2.span.shrink_to_hi(), - }); + err.chaining_sugg = + Some(ComparisonOperatorsCannotBeChainedSugg::Parenthesize { + left: r1.span.shrink_to_lo(), + right: r2.span.shrink_to_hi(), + }); true } Err(expr_err) => { @@ -1385,17 +1386,18 @@ impl<'a> Parser<'a> { // `x > y == z` ( BinOpKind::Lt | BinOpKind::Le | BinOpKind::Gt | BinOpKind::Ge, - AssocOp::Binary(BinOpKind::Eq) + AssocOp::Binary(BinOpKind::Eq), ) => { let snapshot = self.create_snapshot_for_diagnostic(); // At this point it is always valid to enclose the lhs in parentheses, no // further checks are necessary. match self.parse_expr() { Ok(_) => { - err.chaining_sugg = Some(ComparisonOperatorsCannotBeChainedSugg::Parenthesize { - left: l1.span.shrink_to_lo(), - right: r1.span.shrink_to_hi(), - }); + err.chaining_sugg = + Some(ComparisonOperatorsCannotBeChainedSugg::Parenthesize { + left: l1.span.shrink_to_lo(), + right: r1.span.shrink_to_hi(), + }); true } Err(expr_err) => { @@ -1405,7 +1407,7 @@ impl<'a> Parser<'a> { } } } - _ => false + _ => false, }; } false diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index e5de0d972df6a..957ed9ab55e0a 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1107,9 +1107,7 @@ impl<'a> Parser<'a> { match &*components { // 1e2 - [IdentLike(i)] => { - DestructuredFloat::Single(Symbol::intern(i), span) - } + [IdentLike(i)] => DestructuredFloat::Single(Symbol::intern(i), span), // 1. [IdentLike(left), Punct('.')] => { let (left_span, dot_span) = if can_take_span_apart() { @@ -1126,7 +1124,8 @@ impl<'a> Parser<'a> { [IdentLike(left), Punct('.'), IdentLike(right)] => { let (left_span, dot_span, right_span) = if can_take_span_apart() { let left_span = span.with_hi(span.lo() + BytePos::from_usize(left.len())); - let dot_span = span.with_lo(left_span.hi()).with_hi(left_span.hi() + BytePos(1)); + let dot_span = + span.with_lo(left_span.hi()).with_hi(left_span.hi() + BytePos(1)); let right_span = span.with_lo(dot_span.hi()); (left_span, dot_span, right_span) } else { diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index 6ca7f89c76776..1b1d7ddb24b1b 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -26,18 +26,16 @@ impl<'a> Parser<'a> { | MetaVarKind::Pat(_) | MetaVarKind::Expr { .. } | MetaVarKind::Ty { .. } - | MetaVarKind::Literal // `true`, `false` | MetaVarKind::Meta { .. } | MetaVarKind::Path => true, + // `true`, `false` + MetaVarKind::Literal => true, - MetaVarKind::Item - | MetaVarKind::Block - | MetaVarKind::Vis - | MetaVarKind::Guard => false, + MetaVarKind::Item | MetaVarKind::Block | MetaVarKind::Vis | MetaVarKind::Guard => { + false + } - MetaVarKind::Ident - | MetaVarKind::Lifetime - | MetaVarKind::TT => unreachable!(), + MetaVarKind::Ident | MetaVarKind::Lifetime | MetaVarKind::TT => unreachable!(), } } diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 5d3ea7e2c237c..92a0f14f3e94e 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -22,7 +22,7 @@ use rustc_middle::ty::{self, AssocTag, TyCtxt}; use rustc_middle::{bug, span_bug}; use rustc_session::config::CrateType; use rustc_session::lint::builtin::{DEAD_CODE, DEAD_CODE_PUB_IN_BINARY}; -use rustc_session::lint::{self, Lint, LintExpectationId}; +use rustc_session::lint::{self, Lint, StableLintExpectationId}; use rustc_span::{Symbol, kw}; use crate::errors::{ @@ -1035,7 +1035,7 @@ fn mark_live_symbols_and_ignored_derived_traits( struct DeadItem { def_id: LocalDefId, name: Symbol, - level_plus: (lint::Level, Option), + level_plus: (lint::Level, Option), } struct DeadVisitor<'tcx> { @@ -1082,7 +1082,10 @@ impl<'tcx> DeadVisitor<'tcx> { ShouldWarnAboutField::Yes } - fn def_lint_level_plus(&self, id: LocalDefId) -> (lint::Level, Option) { + fn def_lint_level_plus( + &self, + id: LocalDefId, + ) -> (lint::Level, Option) { let hir_id = self.tcx.local_def_id_to_hir_id(id); let level_spec = self.tcx.lint_level_spec_at_node(self.target_lint, hir_id); (level_spec.level(), level_spec.lint_id()) @@ -1267,7 +1270,7 @@ impl<'tcx> DeadVisitor<'tcx> { return; } // FIXME: `dead_codes` should probably be morally equivalent to - // `IndexMap<(Level, LintExpectationId), (DefId, Symbol)>` + // `IndexMap<(Level, StableLintExpectationId), (DefId, Symbol)>` dead_codes.sort_by_key(|v| v.level_plus.0); for group in dead_codes.chunk_by(|a, b| a.level_plus == b.level_plus) { self.lint_at_single_level(&group, participle, Some(def_id), report_on); diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 8be99499cd17a..726f81b42ad40 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -4429,7 +4429,13 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } Some(res) } - Res::Def(DefKind::Ctor(..) | DefKind::Const { .. } | DefKind::AssocConst { .. } | DefKind::Static { .. }, _) => { + Res::Def( + DefKind::Ctor(..) + | DefKind::Const { .. } + | DefKind::AssocConst { .. } + | DefKind::Static { .. }, + _, + ) => { // This is unambiguously a fresh binding, either syntactically // (e.g., `IDENT @ PAT` or `ref IDENT`) or because `IDENT` resolves // to something unusable as a pattern (e.g., constructor function), @@ -4461,7 +4467,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { article: res.article(), shadowed_binding: res, shadowed_binding_span: self.r.def_span(def_id), - } + }, ); None } @@ -4474,7 +4480,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { // so delay a bug instead of ICEing. self.r.dcx().span_delayed_bug( ident.span, - "unexpected `SelfCtor` in pattern, expected identifier" + "unexpected `SelfCtor` in pattern, expected identifier", ); None } diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index c83689f37da59..873aad38a7854 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -3474,7 +3474,11 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { if !self.diag_metadata.currently_processing_generic_args && !single_uppercase_char { return (None, None); } - match (self.diag_metadata.current_item, single_uppercase_char, self.diag_metadata.currently_processing_generic_args) { + match ( + self.diag_metadata.current_item, + single_uppercase_char, + self.diag_metadata.currently_processing_generic_args, + ) { (Some(Item { kind: ItemKind::Fn(fn_), .. }), _, _) if fn_.ident.name == sym::main => { // Ignore `fn main()` as we don't want to suggest `fn main()` } @@ -3487,7 +3491,8 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { | kind @ ItemKind::Union(..), .. }), - true, _ + true, + _, ) // Without the 2nd `true`, we'd suggest `impl ` for `impl T` when a type `T` isn't found | (Some(Item { kind: kind @ ItemKind::Impl(..), .. }), true, true) @@ -3507,7 +3512,9 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { let (msg, sugg) = match source { PathSource::Type | PathSource::PreciseCapturingArg(TypeNS) => { - if let Some(err) = self.detect_and_suggest_const_parameter_error(path, source) { + if let Some(err) = + self.detect_and_suggest_const_parameter_error(path, source) + { return (None, Some(err)); } ("you might be missing a type parameter", ident) @@ -3522,8 +3529,10 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { let span = if let [.., bound] = ¶m.bounds[..] { bound.span() } else if let GenericParam { - kind: GenericParamKind::Const { ty, span: _, default }, .. - } = param { + kind: GenericParamKind::Const { ty, span: _, default }, + .. + } = param + { default.as_ref().map(|def| def.value.span).unwrap_or(ty.span) } else { param.ident.span @@ -3534,12 +3543,10 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { }; // Do not suggest if this is coming from macro expansion. if span.can_be_used_for_suggestions() { - return (Some(( - span.shrink_to_hi(), - msg, - sugg, - Applicability::MaybeIncorrect, - )), None); + return ( + Some((span.shrink_to_hi(), msg, sugg, Applicability::MaybeIncorrect)), + None, + ); } } } diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index d1822b1cb15e4..378826c60f571 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -1273,8 +1273,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { PathResult::NonModule(..) | // HACK(Urgau): This shouldn't be necessary PathResult::Failed { is_error_from_last_segment: false, .. } => { - self.dcx() - .emit_err(errors::CfgAccessibleUnsure { span }); + self.dcx().emit_err(errors::CfgAccessibleUnsure { span }); // If we get a partially resolved NonModule in one namespace, we should get the // same result in any other namespaces, so we can return early. diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 003164e8f9054..1fe5aa1fd12b3 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -117,9 +117,6 @@ pub struct Session { /// This only ever stores a `LintStore` but we don't want a dependency on that type here. pub lint_store: Option>, - /// Cap lint level specified by a driver specifically. - pub driver_lint_caps: FxHashMap, - /// Tracks the current behavior of the CTFE engine when an error occurs. /// Options range from returning the error without a backtrace to returning an error /// and immediately printing the backtrace to stderr. @@ -1005,7 +1002,6 @@ fn default_emitter(sopts: &config::Options, source_map: Arc) -> Box, target: Target, cfg_version: &'static str, ice_file: Option, @@ -1111,7 +1107,6 @@ pub fn build_session( timings, code_stats: Default::default(), lint_store: None, - driver_lint_caps, ctfe_backtrace, miri_unleashed_features: Lock::new(Default::default()), asm_arch, diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 4b67cada078a4..bf881feb60158 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -73,10 +73,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { root_obligation.cause.code().peel_derives() && !obligation.predicate.has_non_region_infer() { - if let Some(cause) = self - .tcx - .diagnostic_hir_wf_check((tcx.erase_and_anonymize_regions(obligation.predicate), *wf_loc)) - { + if let Some(cause) = self.tcx.diagnostic_hir_wf_check(( + tcx.erase_and_anonymize_regions(obligation.predicate), + *wf_loc, + )) { obligation.cause = cause.clone(); span = obligation.cause.span; } @@ -89,13 +89,14 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } = *obligation.cause.code() { debug!("ObligationCauseCode::CompareImplItemObligation"); - return self.report_extra_impl_obligation( - span, - impl_item_def_id, - trait_item_def_id, - &format!("`{}`", obligation.predicate), - ) - .emit() + return self + .report_extra_impl_obligation( + span, + impl_item_def_id, + trait_item_def_id, + &format!("`{}`", obligation.predicate), + ) + .emit(); } // Report a const-param specific error @@ -116,7 +117,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // // We rely on a few heuristics to identify cases where this root // obligation is more important than the leaf obligation: - let (main_trait_predicate, main_obligation) = if let ty::PredicateKind::Clause( + let (main_trait_predicate, main_obligation) = + if let ty::PredicateKind::Clause( ty::ClauseKind::Trait(root_pred) ) = root_obligation.predicate.kind().skip_binder() && !leaf_trait_predicate.self_ty().skip_binder().has_escaping_bound_vars() @@ -146,26 +148,24 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // The root trait is not `Unsize`, as to avoid talking about it in // `tests/ui/coercion/coerce-issue-49593-box-never.rs`. && !self.tcx.is_lang_item(root_pred.def_id(), LangItem::Unsize) - { - ( - self.resolve_vars_if_possible( - root_obligation.predicate.kind().rebind(root_pred), - ), - root_obligation, - ) - } else { - (leaf_trait_predicate, &obligation) - }; + { + ( + self.resolve_vars_if_possible( + root_obligation.predicate.kind().rebind(root_pred), + ), + root_obligation, + ) + } else { + (leaf_trait_predicate, &obligation) + }; - if let Some(guar) = self.emit_specialized_closure_kind_error( - &obligation, - leaf_trait_predicate, - ) { + if let Some(guar) = self + .emit_specialized_closure_kind_error(&obligation, leaf_trait_predicate) + { return guar; } - if let Err(guar) = leaf_trait_predicate.error_reported() - { + if let Err(guar) = leaf_trait_predicate.error_reported() { return guar; } // Silence redundant errors on binding access that are already @@ -185,29 +185,32 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { }) .unwrap_or_default(); - let CustomDiagnostic { - message, - label, - notes, - parent_label, - } = self.on_unimplemented_note(main_trait_predicate, main_obligation, &mut long_ty_file); + let CustomDiagnostic { message, label, notes, parent_label } = self + .on_unimplemented_note( + main_trait_predicate, + main_obligation, + &mut long_ty_file, + ); let have_alt_message = message.is_some() || label.is_some(); - let message = message.unwrap_or_else(|| self.get_standard_error_message( - main_trait_predicate, - None, - post_message, - &mut long_ty_file, - )); - let is_try_conversion = self.is_try_conversion(span, main_trait_predicate.def_id()); + let message = message.unwrap_or_else(|| { + self.get_standard_error_message( + main_trait_predicate, + None, + post_message, + &mut long_ty_file, + ) + }); + let is_try_conversion = + self.is_try_conversion(span, main_trait_predicate.def_id()); let is_question_mark = matches!( root_obligation.cause.code().peel_derives(), ObligationCauseCode::QuestionMark, - ) && !( - self.tcx.is_diagnostic_item(sym::FromResidual, main_trait_predicate.def_id()) - || self.tcx.is_lang_item(main_trait_predicate.def_id(), LangItem::Try) - ); + ) && !(self + .tcx + .is_diagnostic_item(sym::FromResidual, main_trait_predicate.def_id()) + || self.tcx.is_lang_item(main_trait_predicate.def_id(), LangItem::Try)); let is_unsize = self.tcx.is_lang_item(leaf_trait_predicate.def_id(), LangItem::Unsize); let question_mark_message = "the question mark operation (`?`) implicitly \ @@ -240,13 +243,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { (message, notes) }; - let (err_msg, safe_transmute_explanation) = if self.tcx.is_lang_item( - main_trait_predicate.def_id(), - LangItem::TransmuteTrait, - ) { + let (err_msg, safe_transmute_explanation) = if self + .tcx + .is_lang_item(main_trait_predicate.def_id(), LangItem::TransmuteTrait) + { // Recompute the safe transmute reason and use that for the error reporting - let (report_obligation, report_pred) = - self.select_transmute_obligation_for_reporting( + let (report_obligation, report_pred) = self + .select_transmute_obligation_for_reporting( &obligation, main_trait_predicate, root_obligation, @@ -258,13 +261,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { span, ) { GetSafeTransmuteErrorAndReason::Silent => { - return self.dcx().span_delayed_bug( - span, "silent safe transmute error" - ); - } - GetSafeTransmuteErrorAndReason::Default => { - (message, None) + return self + .dcx() + .span_delayed_bug(span, "silent safe transmute error"); } + GetSafeTransmuteErrorAndReason::Default => (message, None), GetSafeTransmuteErrorAndReason::Error { err_msg, safe_transmute_explanation, @@ -285,15 +286,14 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { { let trait_ref = leaf_trait_predicate.skip_binder().trait_ref; - if let Some(found_ty) = trait_ref.args.get(1).and_then(|arg| arg.as_type()) + if let Some(found_ty) = + trait_ref.args.get(1).and_then(|arg| arg.as_type()) { let ty = main_trait_predicate.skip_binder().self_ty(); - if let Some(cast_ty) = self.find_explicit_cast_type( - obligation.param_env, - found_ty, - ty, - ) { + if let Some(cast_ty) = + self.find_explicit_cast_type(obligation.param_env, found_ty, ty) + { let found_ty_str = self.tcx.short_string(found_ty, &mut long_ty_file); let cast_ty_str = @@ -306,13 +306,16 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } - *err.long_ty_path() = long_ty_file; let mut suggested = false; let mut noted_missing_impl = false; if is_try_conversion || is_question_mark { - (suggested, noted_missing_impl) = self.try_conversion_context(&obligation, main_trait_predicate, &mut err); + (suggested, noted_missing_impl) = self.try_conversion_context( + &obligation, + main_trait_predicate, + &mut err, + ); } suggested |= self.detect_negative_literal( @@ -378,8 +381,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } let ty_span = match leaf_trait_predicate.self_ty().skip_binder().kind() { - ty::Adt(def, _) if def.did().is_local() - && !self.can_suggest_derive(&obligation, leaf_trait_predicate) => self.tcx.def_span(def.did()), + ty::Adt(def, _) + if def.did().is_local() + && !self + .can_suggest_derive(&obligation, leaf_trait_predicate) => + { + self.tcx.def_span(def.did()) + } _ => DUMMY_SP, }; if let Some(s) = label { @@ -391,8 +399,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // `std::marker::Sized` is not implemented for `T`" as we will point // at the type param with a label to suggest constraining it. && !self.tcx.is_diagnostic_item(sym::FromResidual, leaf_trait_predicate.def_id()) - // Don't say "the trait `FromResidual>` is - // not implemented for `Result`". + // Don't say "the trait `FromResidual>` is + // not implemented for `Result`". { // We do this just so that the JSON output's `help` position is the // right one and not `file.rs:1:1`. The render is the same. @@ -404,7 +412,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } else if let Some(custom_explanation) = safe_transmute_explanation { err.span_label(span, custom_explanation); - } else if (explanation.len() > self.tcx.sess.diagnostic_width() || ty_span != DUMMY_SP) && !noted_missing_impl { + } else if (explanation.len() > self.tcx.sess.diagnostic_width() + || ty_span != DUMMY_SP) + && !noted_missing_impl + { // Really long types don't look good as span labels, instead move it // to a `help`. err.span_label(span, "unsatisfied trait bound"); @@ -423,7 +434,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { if let ObligationCauseCode::Coercion { source, target } = *obligation.cause.code().peel_derives() { - if self.tcx.is_lang_item(leaf_trait_predicate.def_id(), LangItem::Sized) { + if self.tcx.is_lang_item(leaf_trait_predicate.def_id(), LangItem::Sized) + { self.suggest_borrowing_for_object_cast( &mut err, root_obligation, @@ -445,10 +457,20 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { err.span_label(tcx.def_span(body), s); } - self.suggest_floating_point_literal(&obligation, &mut err, leaf_trait_predicate); - self.suggest_dereferencing_index(&obligation, &mut err, leaf_trait_predicate); - suggested |= self.suggest_dereferences(&obligation, &mut err, leaf_trait_predicate); - suggested |= self.suggest_fn_call(&obligation, &mut err, leaf_trait_predicate); + self.suggest_floating_point_literal( + &obligation, + &mut err, + leaf_trait_predicate, + ); + self.suggest_dereferencing_index( + &obligation, + &mut err, + leaf_trait_predicate, + ); + suggested |= + self.suggest_dereferences(&obligation, &mut err, leaf_trait_predicate); + suggested |= + self.suggest_fn_call(&obligation, &mut err, leaf_trait_predicate); suggested |= self.suggest_cast_to_fn_pointer( &obligation, &mut err, @@ -456,15 +478,22 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { main_trait_predicate, span, ); - suggested |= - self.suggest_remove_reference(&obligation, &mut err, leaf_trait_predicate); + suggested |= self.suggest_remove_reference( + &obligation, + &mut err, + leaf_trait_predicate, + ); suggested |= self.suggest_semicolon_removal( &obligation, &mut err, span, leaf_trait_predicate, ); - self.note_different_trait_with_same_name(&mut err, &obligation, leaf_trait_predicate); + self.note_different_trait_with_same_name( + &mut err, + &obligation, + leaf_trait_predicate, + ); self.note_adt_version_mismatch(&mut err, leaf_trait_predicate); self.suggest_remove_await(&obligation, &mut err); self.suggest_derive(&obligation, &mut err, leaf_trait_predicate); @@ -478,7 +507,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ); } - if self.suggest_add_clone_to_arg(&obligation, &mut err, leaf_trait_predicate) { + if self.suggest_add_clone_to_arg( + &obligation, + &mut err, + leaf_trait_predicate, + ) { return err.emit(); } @@ -553,11 +586,18 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { \ for more information)", ); - err.help("you might have intended to use the type `()` here instead"); + err.help( + "you might have intended to use the type `()` here instead", + ); } } - self.explain_hrtb_projection(&mut err, leaf_trait_predicate, obligation.param_env, &obligation.cause); + self.explain_hrtb_projection( + &mut err, + leaf_trait_predicate, + obligation.param_env, + &obligation.cause, + ); self.suggest_desugaring_async_fn_in_trait(&mut err, main_trait_predicate); // Return early if the trait is Debug or Display and the invocation @@ -586,9 +626,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { err } - ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(predicate)) => { - self.report_host_effect_error(bound_predicate.rebind(predicate), &obligation, span) - } + ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(predicate)) => self + .report_host_effect_error( + bound_predicate.rebind(predicate), + &obligation, + span, + ), ty::PredicateKind::Subtype(predicate) => { // Errors for Subtype predicates show up as @@ -668,17 +711,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } - // Errors for `ConstEvaluatable` predicates show up as - // `SelectionError::ConstEvalFailure`, - // not `Unimplemented`. + // Errors for `ConstEvaluatable`, `ConstEquate` predicates show up as + // `SelectionError::ConstEvalFailure`, not `Unimplemented`. + // Ambiguous predicates should never error. + // We never return `Err` when proving `UnstableFeature` goal. ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..)) - // Errors for `ConstEquate` predicates show up as - // `SelectionError::ConstEvalFailure`, - // not `Unimplemented`. | ty::PredicateKind::ConstEquate { .. } - // Ambiguous predicates should never error | ty::PredicateKind::Ambiguous - // We never return Err when proving UnstableFeature goal. | ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature { .. }) | ty::PredicateKind::NormalizesTo { .. } | ty::PredicateKind::AliasRelate { .. } @@ -736,12 +775,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } // Already reported in the query. - SelectionError::NotConstEvaluatable(NotConstEvaluatable::Error(guar)) | - // Already reported. - SelectionError::Overflow(OverflowError::Error(guar)) => { + SelectionError::NotConstEvaluatable(NotConstEvaluatable::Error(guar)) + | SelectionError::Overflow(OverflowError::Error(guar)) => { self.set_tainted_by_errors(guar); - return guar - }, + return guar; + } SelectionError::Overflow(_) => { bug!("overflow should be handled before the `report_selection_error` path"); diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 646945990a1d5..af104a56202b0 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -740,7 +740,11 @@ impl<'tcx> AutoTraitFinder<'tcx> { ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(binder)) => { let binder = bound_predicate.rebind(binder); selcx.infcx.enter_forall(binder, |pred| { - selcx.infcx.register_region_outlives_constraint(pred, ty::VisibleForLeakCheck::Yes,&dummy_cause); + selcx.infcx.register_region_outlives_constraint( + pred, + ty::VisibleForLeakCheck::Yes, + &dummy_cause, + ); }); } ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(binder)) => { @@ -757,11 +761,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { ); } (Some(ty::OutlivesPredicate(t_a, r_b)), _) => { - selcx.infcx.register_type_outlives_constraint( - t_a, - r_b, - &dummy_cause, - ); + selcx.infcx.register_type_outlives_constraint(t_a, r_b, &dummy_cause); } _ => {} }; @@ -769,11 +769,8 @@ impl<'tcx> AutoTraitFinder<'tcx> { ty::PredicateKind::ConstEquate(c1, c2) => { let evaluate = |c: ty::Const<'tcx>| { if let ty::ConstKind::Unevaluated(unevaluated) = c.kind() { - let ct = super::try_evaluate_const( - selcx.infcx, - c, - obligation.param_env, - ); + let ct = + super::try_evaluate_const(selcx.infcx, c, obligation.param_env); if let Err(EvaluateConstErr::InvalidConstParamTy(_)) = ct { self.tcx.dcx().emit_err(UnableToConstructConstantValue { @@ -790,8 +787,11 @@ impl<'tcx> AutoTraitFinder<'tcx> { match (evaluate(c1), evaluate(c2)) { (Ok(c1), Ok(c2)) => { - match selcx.infcx.at(&obligation.cause, obligation.param_env).eq(DefineOpaqueTypes::Yes,c1, c2) - { + match selcx.infcx.at(&obligation.cause, obligation.param_env).eq( + DefineOpaqueTypes::Yes, + c1, + c2, + ) { Ok(_) => (), Err(_) => return false, } @@ -810,12 +810,13 @@ impl<'tcx> AutoTraitFinder<'tcx> { | ty::PredicateKind::AliasRelate(..) | ty::PredicateKind::DynCompatible(..) | ty::PredicateKind::Subtype(..) - // FIXME(generic_const_exprs): you can absolutely add this as a where clauses - | ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..)) | ty::PredicateKind::Coerce(..) | ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature(_)) | ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(..)) => {} ty::PredicateKind::Ambiguous => return false, + + // FIXME(generic_const_exprs): you can absolutely add this as a where clauses + ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..)) => return false, }; } true diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index b81d466f9106a..a018a150a7067 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -223,7 +223,17 @@ fn predicate_references_self<'tcx>( match predicate.kind().skip_binder() { ty::ClauseKind::Trait(ref data) => { // In the case of a trait predicate, we can skip the "self" type. - data.trait_ref.args[1..].iter().any(|&arg| contains_illegal_self_type_reference(tcx, trait_def_id, arg, allow_self_projections)).then_some(sp) + data.trait_ref.args[1..] + .iter() + .any(|&arg| { + contains_illegal_self_type_reference( + tcx, + trait_def_id, + arg, + allow_self_projections, + ) + }) + .then_some(sp) } ty::ClauseKind::Projection(ref data) => { // And similarly for projections. This should be redundant with @@ -241,18 +251,31 @@ fn predicate_references_self<'tcx>( // // This is ALT2 in issue #56288, see that for discussion of the // possible alternatives. - data.projection_term.args[1..].iter().any(|&arg| contains_illegal_self_type_reference(tcx, trait_def_id, arg, allow_self_projections)).then_some(sp) + data.projection_term.args[1..] + .iter() + .any(|&arg| { + contains_illegal_self_type_reference( + tcx, + trait_def_id, + arg, + allow_self_projections, + ) + }) + .then_some(sp) + } + ty::ClauseKind::ConstArgHasType(_ct, ty) => { + contains_illegal_self_type_reference(tcx, trait_def_id, ty, allow_self_projections) + .then_some(sp) } - ty::ClauseKind::ConstArgHasType(_ct, ty) => contains_illegal_self_type_reference(tcx, trait_def_id, ty, allow_self_projections).then_some(sp), ty::ClauseKind::WellFormed(..) | ty::ClauseKind::TypeOutlives(..) | ty::ClauseKind::RegionOutlives(..) - // FIXME(generic_const_exprs): this can mention `Self` - | ty::ClauseKind::ConstEvaluatable(..) | ty::ClauseKind::HostEffect(..) - | ty::ClauseKind::UnstableFeature(_) - => None, + | ty::ClauseKind::UnstableFeature(_) => None, + + // FIXME(generic_const_exprs): this can mention `Self` + ty::ClauseKind::ConstEvaluatable(..) => None, } } diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index ce8f05637f9a6..914e103afded3 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -464,7 +464,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { bug!("AliasRelate is only used by the new solver") } ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature(_)) => { - unreachable!("unexpected higher ranked `UnstableFeature` goal") + unreachable!("unexpected higher ranked `UnstableFeature` goal") } }, Some(pred) => match pred { diff --git a/compiler/rustc_transmute/src/maybe_transmutable/mod.rs b/compiler/rustc_transmute/src/maybe_transmutable/mod.rs index 062de4b5d08a7..b748611be383f 100644 --- a/compiler/rustc_transmute/src/maybe_transmutable/mod.rs +++ b/compiler/rustc_transmute/src/maybe_transmutable/mod.rs @@ -330,7 +330,7 @@ impl Answer { // If either is an error, return it | (Answer::No(reason), _) | (_, Answer::No(reason)) => Answer::No(reason), // If only one side has a condition, pass it along - | (Answer::Yes, other) | (other, Answer::Yes) => other, + (Answer::Yes, other) | (other, Answer::Yes) => other, // If both sides have IfAll conditions, merge them (Answer::If(Condition::IfAll(mut lhs)), Answer::If(Condition::IfAll(ref mut rhs))) => { lhs.append(rhs); diff --git a/compiler/rustc_ty_utils/src/sig_types.rs b/compiler/rustc_ty_utils/src/sig_types.rs index ab4bfd998cf34..ebec1888e6a95 100644 --- a/compiler/rustc_ty_utils/src/sig_types.rs +++ b/compiler/rustc_ty_utils/src/sig_types.rs @@ -41,10 +41,13 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( try_visit!(visitor.visit(span, pred.skip_norm_wip())); } } - // Walk over the type behind the alias - DefKind::TyAlias { .. } | DefKind::AssocTy | - // Walk over the type of the item - DefKind::Static { .. } | DefKind::Const { .. } | DefKind::AssocConst { .. } | DefKind::AnonConst => { + // Walk over the type behind the alias or the type of the item + DefKind::TyAlias { .. } + | DefKind::AssocTy + | DefKind::Static { .. } + | DefKind::Const { .. } + | DefKind::AssocConst { .. } + | DefKind::AnonConst => { if let Some(ty) = tcx.hir_node_by_def_id(item).ty() { // If the type of the item uses `_`, we're gonna error out anyway, but // typeck (which type_of invokes below), will call back into opaque_types_defined_by @@ -53,14 +56,21 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( return V::Result::output(); } // Associated types in traits don't necessarily have a type that we can visit - try_visit!(visitor.visit(ty.span, tcx.type_of(item).instantiate_identity().skip_norm_wip())); + try_visit!( + visitor + .visit(ty.span, tcx.type_of(item).instantiate_identity().skip_norm_wip()) + ); } for (pred, span) in tcx.explicit_predicates_of(item).instantiate_identity(tcx) { try_visit!(visitor.visit(span, pred.skip_norm_wip())); } } DefKind::OpaqueTy => { - for (pred, span) in tcx.explicit_item_bounds(item).iter_identity_copied().map(Unnormalized::skip_norm_wip) { + for (pred, span) in tcx + .explicit_item_bounds(item) + .iter_identity_copied() + .map(Unnormalized::skip_norm_wip) + { try_visit!(visitor.visit(span, pred)); } } @@ -87,15 +97,26 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( DefKind::InlineConst | DefKind::Closure | DefKind::SyntheticCoroutineBody => {} DefKind::Impl { of_trait } => { if of_trait { - let span = tcx.hir_node_by_def_id(item).expect_item().expect_impl().of_trait.unwrap().trait_ref.path.span; - let args = &tcx.impl_trait_ref(item).instantiate_identity().skip_norm_wip().args[1..]; + let span = tcx + .hir_node_by_def_id(item) + .expect_item() + .expect_impl() + .of_trait + .unwrap() + .trait_ref + .path + .span; + let args = + &tcx.impl_trait_ref(item).instantiate_identity().skip_norm_wip().args[1..]; try_visit!(visitor.visit(span, args)); } let span = match tcx.hir_node_by_def_id(item).ty() { Some(ty) => ty.span, _ => tcx.def_span(item), }; - try_visit!(visitor.visit(span, tcx.type_of(item).instantiate_identity().skip_norm_wip())); + try_visit!( + visitor.visit(span, tcx.type_of(item).instantiate_identity().skip_norm_wip()) + ); for (pred, span) in tcx.explicit_predicates_of(item).instantiate_identity(tcx) { try_visit!(visitor.visit(span, pred.skip_norm_wip())); } @@ -105,7 +126,7 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( try_visit!(visitor.visit(span, pred.skip_norm_wip())); } } - | DefKind::Variant + DefKind::Variant | DefKind::TyParam | DefKind::ConstParam | DefKind::Ctor(_, _) @@ -117,7 +138,7 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( ) } // These don't have any types, but are visited during privacy checking. - | DefKind::ExternCrate + DefKind::ExternCrate | DefKind::ForeignMod | DefKind::ForeignTy | DefKind::Macro(_) diff --git a/src/doc/rustc-dev-guide/examples/rustc-interface-example.rs b/src/doc/rustc-dev-guide/examples/rustc-interface-example.rs index 4601d9adbb640..37e971ce568db 100644 --- a/src/doc/rustc-dev-guide/examples/rustc-interface-example.rs +++ b/src/doc/rustc-dev-guide/examples/rustc-interface-example.rs @@ -28,12 +28,11 @@ fn main() { println!("{HELLO}"); } "# - .into(), + .into(), }, - output_dir: None, // Option - output_file: None, // Option - file_loader: None, // Option> - lint_caps: FxHashMap::default(), // FxHashMap + output_dir: None, // Option + output_file: None, // Option + file_loader: None, // Option> // This is a callback from the driver that is called when [`ParseSess`] is created. psess_created: None, //Option> // This is a callback from the driver that is called when we're registering lints; diff --git a/src/doc/rustc-dev-guide/examples/rustc-interface-getting-diagnostics.rs b/src/doc/rustc-dev-guide/examples/rustc-interface-getting-diagnostics.rs index ea2a772703bbd..0ec146f67a0d4 100644 --- a/src/doc/rustc-dev-guide/examples/rustc-interface-getting-diagnostics.rs +++ b/src/doc/rustc-dev-guide/examples/rustc-interface-getting-diagnostics.rs @@ -59,14 +59,13 @@ fn main() { let x: &str = 1; } " - .into(), + .into(), }, crate_cfg: Vec::new(), crate_check_cfg: Vec::new(), output_dir: None, output_file: None, file_loader: None, - lint_caps: rustc_hash::FxHashMap::default(), psess_created: Some(Box::new(|parse_sess| { parse_sess.dcx().set_emitter(Box::new(DebugEmitter { source_map: parse_sess.clone_source_map(), diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 21ce508d8560c..3f5a50e6af197 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -238,7 +238,7 @@ pub(crate) fn create_config( ]; lints_to_show.extend(crate::lint::RUSTDOC_LINTS.iter().map(|lint| lint.name.to_string())); - let (lint_opts, lint_caps) = crate::lint::init_lints(lints_to_show, lint_opts, |lint| { + let lint_opts = crate::lint::init_lints(lints_to_show, lint_opts, |lint| { Some((lint.name_lower(), lint::Allow)) }); @@ -293,7 +293,6 @@ pub(crate) fn create_config( Some(render_options.output.clone()) }, file_loader: None, - lint_caps, psess_created: None, track_state: None, register_lints: Some(Box::new(crate::lint::register_lints)), diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 6ec4aaf282238..6d5e12f0ddb63 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -144,7 +144,7 @@ pub(crate) fn run(dcx: DiagCtxtHandle<'_>, input: Input, options: RustdocOptions lint::builtin::RENAMED_AND_REMOVED_LINTS.name.to_owned(), ]; - let (lint_opts, lint_caps) = init_lints(allowed_lints, options.lint_opts.clone(), |lint| { + let lint_opts = init_lints(allowed_lints, options.lint_opts.clone(), |lint| { if lint.name == invalid_codeblock_attributes_name { None } else { @@ -162,7 +162,7 @@ pub(crate) fn run(dcx: DiagCtxtHandle<'_>, input: Input, options: RustdocOptions search_paths: options.libs.clone(), crate_types, lint_opts, - lint_cap: Some(options.lint_cap.unwrap_or(lint::Forbid)), + lint_cap: None, cg: options.codegen_options.clone(), externs: options.externs.clone(), unstable_features: options.unstable_features, @@ -189,7 +189,6 @@ pub(crate) fn run(dcx: DiagCtxtHandle<'_>, input: Input, options: RustdocOptions output_file: None, output_dir: None, file_loader: None, - lint_caps, psess_created: None, track_state: None, register_lints: Some(Box::new(crate::lint::register_lints)), diff --git a/src/librustdoc/lint.rs b/src/librustdoc/lint.rs index b09ea05688595..1a3e6d4bf51fb 100644 --- a/src/librustdoc/lint.rs +++ b/src/librustdoc/lint.rs @@ -1,6 +1,5 @@ use std::sync::LazyLock as Lazy; -use rustc_data_structures::fx::FxHashMap; use rustc_lint::LintStore; use rustc_lint_defs::{Lint, LintId, declare_tool_lint}; use rustc_session::{Session, lint}; @@ -14,14 +13,12 @@ use rustc_session::{Session, lint}; /// through the "WARNINGS" lint. To prevent this to happen, we set it back to its "normal" level /// inside this function. /// -/// It returns a tuple containing: -/// * Vector of tuples of lints' name and their associated "max" level -/// * HashMap of lint id with their associated "max" level +/// It returns a vector of tuples of lints' name and their associated "max" level pub(crate) fn init_lints( mut allowed_lints: Vec, lint_opts: Vec<(String, lint::Level)>, filter_call: F, -) -> (Vec<(String, lint::Level)>, FxHashMap) +) -> Vec<(String, lint::Level)> where F: Fn(&lint::Lint) -> Option<(String, lint::Level)>, { @@ -36,7 +33,7 @@ where .chain(rustc_lint::SoftLints::lint_vec()) }; - let lint_opts = lints() + lints() .filter_map(|lint| { // Permit feature-gated lints to avoid feature errors when trying to // allow all lints. @@ -47,20 +44,7 @@ where } }) .chain(lint_opts) - .collect::>(); - - let lint_caps = lints() - .filter_map(|lint| { - // We don't want to allow *all* lints so let's ignore - // those ones. - if allowed_lints.iter().any(|l| lint.name == l) { - None - } else { - Some((lint::LintId::of(lint), lint::Allow)) - } - }) - .collect(); - (lint_opts, lint_caps) + .collect::>() } macro_rules! declare_rustdoc_lint { 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 f93f682bc9298..8ec095cc24dde 100644 --- a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs +++ b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs @@ -133,7 +133,7 @@ impl<'tcx> Visitor<'tcx> for NumericFallbackVisitor<'_, 'tcx> { if let Some(fn_sig) = self.cx.tcx.parent_hir_node(expr.hir_id).fn_sig() && let FnRetTy::Return(_ty) = fn_sig.decl.output { - // We cannot check the exact type since it's a `hir::Ty`` which does not implement `is_numeric` + // We cannot check the exact type since it's a `hir::Ty` which does not implement `is_numeric` self.ty_bounds.push(ExplicitTyBound(true)); for stmt in *stmts { self.visit_stmt(stmt); diff --git a/src/tools/clippy/clippy_lints/src/duplicate_mod.rs b/src/tools/clippy/clippy_lints/src/duplicate_mod.rs index cb3cb2479beed..f1837e776e824 100644 --- a/src/tools/clippy/clippy_lints/src/duplicate_mod.rs +++ b/src/tools/clippy/clippy_lints/src/duplicate_mod.rs @@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_help; use rustc_ast::ast::{Crate, Inline, Item, ItemKind, ModKind}; use rustc_errors::MultiSpan; use rustc_lint::{EarlyContext, EarlyLintPass, Level, LintContext}; -use rustc_middle::lint::LevelSpec; +use rustc_middle::lint::UnstableLevelSpec; use rustc_session::impl_lint_pass; use rustc_span::{FileName, Span}; use std::collections::BTreeMap; @@ -51,7 +51,7 @@ impl_lint_pass!(DuplicateMod => [DUPLICATE_MOD]); struct Modules { local_path: PathBuf, spans: Vec, - lint_level_specs: Vec, + lint_level_specs: Vec, } #[derive(Default)] @@ -96,7 +96,7 @@ impl EarlyLintPass for DuplicateMod { .zip(lint_level_specs) .filter_map(|(span, level_spec)| { if let Some(id) = level_spec.lint_id() { - cx.fulfill_expectation(id); + cx.fulfill_expectation(id.into()); } (!matches!(level_spec.level(), Level::Allow | Level::Expect)).then_some(*span) diff --git a/src/tools/miri/src/shims/os_str.rs b/src/tools/miri/src/shims/os_str.rs index db9cb3a7a32bd..78e7f2d418c30 100644 --- a/src/tools/miri/src/shims/os_str.rs +++ b/src/tools/miri/src/shims/os_str.rs @@ -282,7 +282,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { *c = sep; } } - // If this starts with `//?/`, it was probably produced by `unix_to_windows`` and we + // If this starts with `//?/`, it was probably produced by `unix_to_windows` and we // remove the `//?` that got added to get the Unix path back out. if path.get(0..4) == Some(&[sep, sep, b'?'.into(), sep]) { // Remove first 3 characters. It still starts with `/` so it is absolute on Unix. diff --git a/src/tools/run-make-support/src/external_deps/rustc.rs b/src/tools/run-make-support/src/external_deps/rustc.rs index e8645e00e1852..b5d9593ae9a6a 100644 --- a/src/tools/run-make-support/src/external_deps/rustc.rs +++ b/src/tools/run-make-support/src/external_deps/rustc.rs @@ -190,14 +190,14 @@ impl Rustc { self } - /// Specify path to the output file. Equivalent to `-o`` in rustc. + /// Specify path to the output file. Equivalent to `-o` in rustc. pub fn output>(&mut self, path: P) -> &mut Self { self.cmd.arg("-o"); self.cmd.arg(path.as_ref()); self } - /// Specify path to the output directory. Equivalent to `--out-dir`` in rustc. + /// Specify path to the output directory. Equivalent to `--out-dir` in rustc. pub fn out_dir>(&mut self, path: P) -> &mut Self { self.cmd.arg("--out-dir"); self.cmd.arg(path.as_ref()); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs b/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs index ad1c3fb709c9d..9582f2ceba831 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs @@ -232,11 +232,11 @@ pub fn is_inherent_impl_coherent(db: &dyn HirDatabase, def_map: &DefMap, impl_id /// Checks whether the impl satisfies the orphan rules. /// -/// Given `impl Trait for T0`, an `impl`` is valid only if at least one of the following is true: +/// Given `impl Trait for T0`, an `impl` is valid only if at least one of the following is true: /// - Trait is a local trait /// - All of -/// - At least one of the types `T0..=Tn`` must be a local type. Let `Ti`` be the first such type. -/// - No uncovered type parameters `P1..=Pn` may appear in `T0..Ti`` (excluding `Ti`) +/// - At least one of the types `T0..=Tn` must be a local type. Let `Ti` be the first such type. +/// - No uncovered type parameters `P1..=Pn` may appear in `T0..Ti` (excluding `Ti`) pub fn check_orphan_rules<'db>(db: &'db dyn HirDatabase, impl_: ImplId) -> bool { let Some(impl_trait) = db.impl_trait(impl_) else { // not a trait impl @@ -277,10 +277,10 @@ pub fn check_orphan_rules<'db>(db: &'db dyn HirDatabase, impl_: ImplId) -> bool } } }; - // - At least one of the types `T0..=Tn`` must be a local type. Let `Ti`` be the first such type. + // - At least one of the types `T0..=Tn` must be a local type. Let `Ti` be the first such type. // FIXME: param coverage - // - No uncovered type parameters `P1..=Pn` may appear in `T0..Ti`` (excluding `Ti`) + // - No uncovered type parameters `P1..=Pn` may appear in `T0..Ti` (excluding `Ti`) let is_not_orphan = trait_ref.args.types().any(|ty| match unwrap_fundamental(ty).kind() { TyKind::Adt(adt_def, _) => is_local(adt_def.def_id().module(db).krate(db)), TyKind::Error(_) => true, diff --git a/src/tools/rust-analyzer/crates/mbe/src/parser.rs b/src/tools/rust-analyzer/crates/mbe/src/parser.rs index 796ee62d48e3a..9fbd06cf88626 100644 --- a/src/tools/rust-analyzer/crates/mbe/src/parser.rs +++ b/src/tools/rust-analyzer/crates/mbe/src/parser.rs @@ -109,7 +109,7 @@ pub(crate) enum Op { }, Count { name: Symbol, - // FIXME: `usize`` once we drop support for 1.76 + // FIXME: `usize` once we drop support for 1.76 depth: Option, }, Concat { diff --git a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs index 29a19bc32e453..675533645d0db 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs @@ -748,7 +748,7 @@ impl ProjectWorkspace { .packages() .filter_map(|pkg| { if ws[pkg].is_local { - // the local ones are included in the main `PackageRoot`` below + // the local ones are included in the main `PackageRoot` below return None; } let pkg_root = ws[pkg].manifest.parent().to_path_buf(); diff --git a/tests/ui-fulldeps/run-compiler-twice.rs b/tests/ui-fulldeps/run-compiler-twice.rs index d99d9c42d547f..6afb88d24cff2 100644 --- a/tests/ui-fulldeps/run-compiler-twice.rs +++ b/tests/ui-fulldeps/run-compiler-twice.rs @@ -64,7 +64,6 @@ fn compile(code: String, output: PathBuf, sysroot: Sysroot, linker: Option<&Path output_dir: None, ice_file: None, file_loader: None, - lint_caps: Default::default(), psess_created: None, track_state: None, register_lints: None, diff --git a/tests/ui/async-await/async-closures/dont-ice-when-body-tainted-by-errors.rs b/tests/ui/async-await/async-closures/dont-ice-when-body-tainted-by-errors.rs index f90d10ebe854b..1bbff34292c39 100644 --- a/tests/ui/async-await/async-closures/dont-ice-when-body-tainted-by-errors.rs +++ b/tests/ui/async-await/async-closures/dont-ice-when-body-tainted-by-errors.rs @@ -11,7 +11,7 @@ pub fn main() { // Type error here taints the environment. This causes us to fallback all // variables to `Error`. This means that when we compute the upvars for the // *outer* coroutine-closure, we don't actually see any upvars since `MemCategorization` - // and `ExprUseVisitor`` will bail early when it sees error. This means + // and `ExprUseVisitor` will bail early when it sees error. This means // that our underlying assumption that the parent and child captures are // compatible ends up being broken, previously leading to an ICE. trait_error::<()>(); diff --git a/tests/ui/eii/default/auxiliary/decl_with_default.rs b/tests/ui/eii/default/auxiliary/decl_with_default.rs index 8d962c19c94d9..ba855cb854afd 100644 --- a/tests/ui/eii/default/auxiliary/decl_with_default.rs +++ b/tests/ui/eii/default/auxiliary/decl_with_default.rs @@ -1,4 +1,3 @@ -//@ no-prefer-dynamic #![crate_type = "rlib"] #![feature(extern_item_impls)] diff --git a/tests/ui/eii/default/auxiliary/decl_with_default_panics.rs b/tests/ui/eii/default/auxiliary/decl_with_default_panics.rs index 14778a40cde4a..3867bfb85c9fe 100644 --- a/tests/ui/eii/default/auxiliary/decl_with_default_panics.rs +++ b/tests/ui/eii/default/auxiliary/decl_with_default_panics.rs @@ -1,4 +1,3 @@ -//@ no-prefer-dynamic //@ needs-unwind //@ exec-env:RUST_BACKTRACE=1 #![crate_type = "rlib"] diff --git a/tests/ui/eii/default/auxiliary/impl1.rs b/tests/ui/eii/default/auxiliary/impl1.rs index 3510ea1eb3f27..84edf24e12816 100644 --- a/tests/ui/eii/default/auxiliary/impl1.rs +++ b/tests/ui/eii/default/auxiliary/impl1.rs @@ -1,4 +1,3 @@ -//@ no-prefer-dynamic //@ aux-build: decl_with_default.rs #![crate_type = "rlib"] #![feature(extern_item_impls)] diff --git a/tests/ui/eii/default/call_default.rs b/tests/ui/eii/default/call_default.rs index 8806c7fa7d8ce..07b2a650d3c42 100644 --- a/tests/ui/eii/default/call_default.rs +++ b/tests/ui/eii/default/call_default.rs @@ -1,4 +1,3 @@ -//@ no-prefer-dynamic //@ aux-build: decl_with_default.rs //@ run-pass //@ check-run-results diff --git a/tests/ui/eii/default/call_default_panics.rs b/tests/ui/eii/default/call_default_panics.rs index db664e0cbcb0d..379ba8ea070b6 100644 --- a/tests/ui/eii/default/call_default_panics.rs +++ b/tests/ui/eii/default/call_default_panics.rs @@ -1,4 +1,3 @@ -//@ no-prefer-dynamic //@ aux-build: decl_with_default_panics.rs //@ edition: 2021 //@ run-pass diff --git a/tests/ui/eii/default/call_impl.rs b/tests/ui/eii/default/call_impl.rs index 1a972774beaeb..4553427b8c799 100644 --- a/tests/ui/eii/default/call_impl.rs +++ b/tests/ui/eii/default/call_impl.rs @@ -1,4 +1,3 @@ -//@ no-prefer-dynamic //@ aux-build: decl_with_default.rs //@ aux-build: impl1.rs //@ run-pass diff --git a/tests/ui/eii/duplicate/auxiliary/impl1.rs b/tests/ui/eii/duplicate/auxiliary/impl1.rs index e99932c69b90b..ffa2cd79818cc 100644 --- a/tests/ui/eii/duplicate/auxiliary/impl1.rs +++ b/tests/ui/eii/duplicate/auxiliary/impl1.rs @@ -1,4 +1,3 @@ -//@ no-prefer-dynamic //@ aux-build: decl.rs #![crate_type = "rlib"] #![feature(extern_item_impls)] diff --git a/tests/ui/eii/duplicate/auxiliary/impl2.rs b/tests/ui/eii/duplicate/auxiliary/impl2.rs index 3a09c824b8292..592234f53fd40 100644 --- a/tests/ui/eii/duplicate/auxiliary/impl2.rs +++ b/tests/ui/eii/duplicate/auxiliary/impl2.rs @@ -1,4 +1,3 @@ -//@ no-prefer-dynamic //@ aux-build: decl.rs #![crate_type = "rlib"] #![feature(extern_item_impls)] diff --git a/tests/ui/eii/duplicate/auxiliary/impl3.rs b/tests/ui/eii/duplicate/auxiliary/impl3.rs index 09bdd8509da29..5e9fdaba0bb6b 100644 --- a/tests/ui/eii/duplicate/auxiliary/impl3.rs +++ b/tests/ui/eii/duplicate/auxiliary/impl3.rs @@ -1,4 +1,3 @@ -//@ no-prefer-dynamic //@ aux-build: decl.rs #![crate_type = "rlib"] #![feature(extern_item_impls)] diff --git a/tests/ui/eii/duplicate/auxiliary/impl4.rs b/tests/ui/eii/duplicate/auxiliary/impl4.rs index fd68a83de1252..068cc18d78e6a 100644 --- a/tests/ui/eii/duplicate/auxiliary/impl4.rs +++ b/tests/ui/eii/duplicate/auxiliary/impl4.rs @@ -1,4 +1,3 @@ -//@ no-prefer-dynamic //@ aux-build: decl.rs #![crate_type = "rlib"] #![feature(extern_item_impls)] diff --git a/tests/ui/eii/duplicate/duplicate1.rs b/tests/ui/eii/duplicate/duplicate1.rs index 2128cac70eb30..3d770232af50f 100644 --- a/tests/ui/eii/duplicate/duplicate1.rs +++ b/tests/ui/eii/duplicate/duplicate1.rs @@ -1,4 +1,3 @@ -//@ no-prefer-dynamic //@ aux-build: impl1.rs //@ aux-build: impl2.rs //@ ignore-backends: gcc diff --git a/tests/ui/eii/duplicate/duplicate1.stderr b/tests/ui/eii/duplicate/duplicate1.stderr index 54cc141f88694..f691043e6a597 100644 --- a/tests/ui/eii/duplicate/duplicate1.stderr +++ b/tests/ui/eii/duplicate/duplicate1.stderr @@ -1,10 +1,10 @@ error: multiple implementations of `#[eii1]` - --> $DIR/auxiliary/impl1.rs:10:1 + --> $DIR/auxiliary/impl1.rs:9:1 | LL | fn other(x: u64) { | ^^^^^^^^^^^^^^^^ first implemented here in crate `impl1` | - ::: $DIR/auxiliary/impl2.rs:10:1 + ::: $DIR/auxiliary/impl2.rs:9:1 | LL | fn other(x: u64) { | ---------------- also implemented here in crate `impl2` diff --git a/tests/ui/eii/duplicate/duplicate2.rs b/tests/ui/eii/duplicate/duplicate2.rs index b0f1b1266e4ca..4311969ed8894 100644 --- a/tests/ui/eii/duplicate/duplicate2.rs +++ b/tests/ui/eii/duplicate/duplicate2.rs @@ -1,4 +1,3 @@ -//@ no-prefer-dynamic //@ aux-build: impl1.rs //@ aux-build: impl2.rs //@ aux-build: impl3.rs diff --git a/tests/ui/eii/duplicate/duplicate2.stderr b/tests/ui/eii/duplicate/duplicate2.stderr index 033e43c8b2fbd..492d2b3e6004b 100644 --- a/tests/ui/eii/duplicate/duplicate2.stderr +++ b/tests/ui/eii/duplicate/duplicate2.stderr @@ -1,10 +1,10 @@ error: multiple implementations of `#[eii1]` - --> $DIR/auxiliary/impl1.rs:10:1 + --> $DIR/auxiliary/impl1.rs:9:1 | LL | fn other(x: u64) { | ^^^^^^^^^^^^^^^^ first implemented here in crate `impl1` | - ::: $DIR/auxiliary/impl2.rs:10:1 + ::: $DIR/auxiliary/impl2.rs:9:1 | LL | fn other(x: u64) { | ---------------- also implemented here in crate `impl2` diff --git a/tests/ui/eii/duplicate/duplicate3.rs b/tests/ui/eii/duplicate/duplicate3.rs index 4b2b0fc111b58..4504ba30c246e 100644 --- a/tests/ui/eii/duplicate/duplicate3.rs +++ b/tests/ui/eii/duplicate/duplicate3.rs @@ -1,4 +1,3 @@ -//@ no-prefer-dynamic //@ aux-build: impl1.rs //@ aux-build: impl2.rs //@ aux-build: impl3.rs diff --git a/tests/ui/eii/duplicate/duplicate3.stderr b/tests/ui/eii/duplicate/duplicate3.stderr index 801d40e69c552..f3ca087a27325 100644 --- a/tests/ui/eii/duplicate/duplicate3.stderr +++ b/tests/ui/eii/duplicate/duplicate3.stderr @@ -1,10 +1,10 @@ error: multiple implementations of `#[eii1]` - --> $DIR/auxiliary/impl1.rs:10:1 + --> $DIR/auxiliary/impl1.rs:9:1 | LL | fn other(x: u64) { | ^^^^^^^^^^^^^^^^ first implemented here in crate `impl1` | - ::: $DIR/auxiliary/impl2.rs:10:1 + ::: $DIR/auxiliary/impl2.rs:9:1 | LL | fn other(x: u64) { | ---------------- also implemented here in crate `impl2` diff --git a/tests/ui/eii/static/auxiliary/cross_crate_def.rs b/tests/ui/eii/static/auxiliary/cross_crate_def.rs index 70933440a62be..56d3f6fcdc557 100644 --- a/tests/ui/eii/static/auxiliary/cross_crate_def.rs +++ b/tests/ui/eii/static/auxiliary/cross_crate_def.rs @@ -1,4 +1,3 @@ -//@ no-prefer-dynamic #![crate_type = "rlib"] #![feature(extern_item_impls)] diff --git a/tests/ui/inference/ambiguous-cast-suggestion-issue-41261.rs b/tests/ui/inference/ambiguous-cast-suggestion-issue-41261.rs new file mode 100644 index 0000000000000..b1c4dfb9f1003 --- /dev/null +++ b/tests/ui/inference/ambiguous-cast-suggestion-issue-41261.rs @@ -0,0 +1,19 @@ +//@ edition: 2021 + +// Regression test for issue #41261. +// The diagnostic should point at the ambiguous cast, not at the later method call. + +struct S { + v: Vec<(u32, Vec)>, +} + +impl S { + pub fn remove(&mut self, i: u32) -> Option> { + self.v.get_mut(i as _).map(|&mut (_, ref mut v2)| { + //~^ ERROR type annotations needed + v2.drain(..) + }) + } +} + +fn main() {} diff --git a/tests/ui/inference/ambiguous-cast-suggestion-issue-41261.stderr b/tests/ui/inference/ambiguous-cast-suggestion-issue-41261.stderr new file mode 100644 index 0000000000000..da66f6237203e --- /dev/null +++ b/tests/ui/inference/ambiguous-cast-suggestion-issue-41261.stderr @@ -0,0 +1,17 @@ +error[E0282]: type annotations needed for `&mut (_, _)` + --> $DIR/ambiguous-cast-suggestion-issue-41261.rs:12:37 + | +LL | self.v.get_mut(i as _).map(|&mut (_, ref mut v2)| { + | ^^^^^^^^^^^^^^^^^^^^ +LL | +LL | v2.drain(..) + | -- type must be known at this point + | +help: consider giving this closure parameter an explicit type, where the placeholders `_` are specified + | +LL | self.v.get_mut(i as _).map(|&mut (_, ref mut v2): &mut (_, _)| { + | +++++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/parser/const-block-items/pub.rs b/tests/ui/parser/const-block-items/pub.rs index b76d30d9bda18..4bff11a5a5ad6 100644 --- a/tests/ui/parser/const-block-items/pub.rs +++ b/tests/ui/parser/const-block-items/pub.rs @@ -2,7 +2,7 @@ //@ check-pass -// FIXME(const_block_items): `pub`` is useless here +// FIXME(const_block_items): `pub` is useless here pub const { assert!(true); } diff --git a/tests/ui/parser/raw/raw-idents.rs b/tests/ui/parser/raw/raw-idents.rs index 4e1e6b124c311..fd0a4c7522a09 100644 --- a/tests/ui/parser/raw/raw-idents.rs +++ b/tests/ui/parser/raw/raw-idents.rs @@ -6,7 +6,7 @@ //@[e2024] edition:2024 // Ensure that all (usable as identifier) keywords work as raw identifiers in all positions. -// This was motivated by issue #137128, where `r#move`/`r#static`` did not work as `const` names +// This was motivated by issue #137128, where `r#move`/`r#static` did not work as `const` names // due to a parser check not acounting for raw identifiers. #![crate_type = "lib"] diff --git a/tests/ui/suggestions/suggest-collect.rs b/tests/ui/suggestions/suggest-collect.rs new file mode 100644 index 0000000000000..44e8909fca20f --- /dev/null +++ b/tests/ui/suggestions/suggest-collect.rs @@ -0,0 +1,16 @@ +fn main() { + let _x: String = "hello".chars().map(|c| c); + //~^ ERROR mismatched types + //~| HELP consider using `.collect()` to convert the `Iterator` into a `String` + + let _y: Vec = vec![1, 2, 3].into_iter().map(|x| x); + //~^ ERROR mismatched types + //~| HELP consider using `.collect()` to convert the `Iterator` into a `Vec` + + let res: Result, _> = ["1", "2"].into_iter().map(|s| s.parse::()); + //~^ ERROR mismatched types + //~| HELP consider using `.collect()` to convert the `Iterator` into a `Result, _>` + let (a, b): (Vec, Vec) = vec![1, 2].into_iter().map(|x| (x, x)); + //~^ ERROR mismatched types + //~| HELP consider using `.collect()` to convert the `Iterator` into a `(Vec, Vec)` +} diff --git a/tests/ui/suggestions/suggest-collect.stderr b/tests/ui/suggestions/suggest-collect.stderr new file mode 100644 index 0000000000000..a7bca2bbcaa7b --- /dev/null +++ b/tests/ui/suggestions/suggest-collect.stderr @@ -0,0 +1,63 @@ +error[E0308]: mismatched types + --> $DIR/suggest-collect.rs:2:22 + | +LL | let _x: String = "hello".chars().map(|c| c); + | ------ ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `String`, found `Map, {closure@...}>` + | | + | expected due to this + | + = note: expected struct `String` + found struct `Map, {closure@$DIR/suggest-collect.rs:2:42: 2:45}>` +help: consider using `.collect()` to convert the `Iterator` into a `String` + | +LL | let _x: String = "hello".chars().map(|c| c).collect(); + | ++++++++++ + +error[E0308]: mismatched types + --> $DIR/suggest-collect.rs:6:24 + | +LL | let _y: Vec = vec![1, 2, 3].into_iter().map(|x| x); + | -------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Vec`, found `Map, {closure@...}>` + | | + | expected due to this + | + = note: expected struct `Vec` + found struct `Map, {closure@$DIR/suggest-collect.rs:6:54: 6:57}>` +help: consider using `.collect()` to convert the `Iterator` into a `Vec` + | +LL | let _y: Vec = vec![1, 2, 3].into_iter().map(|x| x).collect(); + | ++++++++++ + +error[E0308]: mismatched types + --> $DIR/suggest-collect.rs:10:36 + | +LL | let res: Result, _> = ["1", "2"].into_iter().map(|s| s.parse::()); + | ------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Result, _>`, found `Map, {closure@...}>` + | | + | expected due to this + | + = note: expected enum `Result, _>` + found struct `Map, {closure@$DIR/suggest-collect.rs:10:63: 10:66}>` +help: consider using `.collect()` to convert the `Iterator` into a `Result, _>` + | +LL | let res: Result, _> = ["1", "2"].into_iter().map(|s| s.parse::()).collect(); + | ++++++++++ + +error[E0308]: mismatched types + --> $DIR/suggest-collect.rs:13:40 + | +LL | let (a, b): (Vec, Vec) = vec![1, 2].into_iter().map(|x| (x, x)); + | -------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(Vec, Vec)`, found `Map, {closure@...}>` + | | + | expected due to this + | + = note: expected tuple `(Vec, Vec)` + found struct `Map, {closure@$DIR/suggest-collect.rs:13:67: 13:70}>` +help: consider using `.collect()` to convert the `Iterator` into a `(Vec, Vec)` + | +LL | let (a, b): (Vec, Vec) = vec![1, 2].into_iter().map(|x| (x, x)).collect(); + | ++++++++++ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/traits/next-solver/normalize/indirectly-constrained-term.rs b/tests/ui/traits/next-solver/normalize/indirectly-constrained-term.rs index 380477c2c3c67..55fb751d26973 100644 --- a/tests/ui/traits/next-solver/normalize/indirectly-constrained-term.rs +++ b/tests/ui/traits/next-solver/normalize/indirectly-constrained-term.rs @@ -17,7 +17,7 @@ // We prove `Projection( as Unconstrained>::Assoc, ())`. This normalizes // ` as Unconstrained>::Assoc` to `?1` and eagerly computes the nested // goals `[Projection(::Assoc, ?1), Trait(?1: NoImpl)]`. -// These goals are both ambiguous. `NormalizesTo`` then returns `?1` as the +// These goals are both ambiguous. `NormalizesTo` then returns `?1` as the // normalized-to type. It discards the nested goals, forcing the certainty of // the normalization to `Maybe`. Unifying `?1` with `()` succeeds¹. However, // this is never propagated to the `?1: NoImpl` goal, as it only exists inside