From cf04547b0b793b55f1255142dc07d3c8437f6815 Mon Sep 17 00:00:00 2001 From: Eric Holk Date: Tue, 30 Aug 2022 12:44:00 -0700 Subject: [PATCH] Address code review comments --- .../rustc_ast_passes/src/ast_validation.rs | 15 +- compiler/rustc_ast_passes/src/feature_gate.rs | 3 + .../src/value_and_place.rs | 1 + compiler/rustc_codegen_ssa/src/mir/block.rs | 2 +- .../rustc_const_eval/src/interpret/cast.rs | 11 +- .../src/transform/validate.rs | 2 +- compiler/rustc_feature/src/active.rs | 2 +- compiler/rustc_middle/src/ty/layout.rs | 11 +- compiler/rustc_monomorphize/src/collector.rs | 4 +- compiler/rustc_parse/src/parser/ty.rs | 4 +- .../src/typeid/typeid_itanium_cxx_abi.rs | 7 +- compiler/rustc_symbol_mangling/src/v0.rs | 8 +- .../src/traits/error_reporting/suggestions.rs | 4 +- .../src/traits/select/confirmation.rs | 8 +- compiler/rustc_traits/src/chalk/lowering.rs | 3 +- compiler/rustc_type_ir/src/sty.rs | 33 ++-- compiler/rustc_typeck/src/check/cast.rs | 9 +- src/test/ui/dyn-star/const.rs | 2 +- src/test/ui/dyn-star/drop.rs | 1 + src/test/ui/dyn-star/error.rs | 1 + src/test/ui/dyn-star/error.stderr | 2 +- src/test/ui/dyn-star/make-dyn-star.rs | 1 + src/test/ui/dyn-star/method.rs | 1 + src/test/ui/dyn-star/syntax.rs | 1 + .../clippy_lints/src/transmute/utils.rs | 27 +-- .../clippy_utils/src/qualify_min_const_fn.rs | 136 ++++++--------- src/tools/clippy/clippy_utils/src/ty.rs | 161 +++++++----------- 27 files changed, 199 insertions(+), 261 deletions(-) diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 5558f0c8c76..6a0a1b08360 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -19,7 +19,6 @@ use rustc_session::lint::builtin::{ DEPRECATED_WHERE_CLAUSE_LOCATION, MISSING_ABI, PATTERNS_IN_FNS_WITHOUT_BODY, }; use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer}; -use rustc_session::parse::feature_err; use rustc_session::Session; use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, sym, Ident}; @@ -754,19 +753,7 @@ impl<'a> AstValidator<'a> { self.maybe_lint_missing_abi(sig_span, ty.id); } } - TyKind::TraitObject(ref bounds, syntax, ..) => { - if syntax == TraitObjectSyntax::DynStar - && !self.session.features_untracked().dyn_star - { - feature_err( - &self.session.parse_sess, - sym::dyn_star, - ty.span, - "dyn* trait objects are unstable", - ) - .emit(); - } - + TyKind::TraitObject(ref bounds, ..) => { let mut any_lifetime_bounds = false; for bound in bounds { if let GenericBound::Outlives(ref lifetime) = *bound { diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index ca5b7a64155..8a2b265c400 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -573,6 +573,9 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { ast::TyKind::Never => { gate_feature_post!(&self, never_type, ty.span, "the `!` type is experimental"); } + ast::TyKind::TraitObject(_, ast::TraitObjectSyntax::DynStar, ..) => { + gate_feature_post!(&self, dyn_star, ty.span, "dyn* trait objects are unstable"); + } _ => {} } visit::walk_ty(self, ty) diff --git a/compiler/rustc_codegen_cranelift/src/value_and_place.rs b/compiler/rustc_codegen_cranelift/src/value_and_place.rs index d58b52851ac..cfaadca9491 100644 --- a/compiler/rustc_codegen_cranelift/src/value_and_place.rs +++ b/compiler/rustc_codegen_cranelift/src/value_and_place.rs @@ -816,6 +816,7 @@ pub(crate) fn assert_assignable<'tcx>( // fn(&T) -> for<'l> fn(&'l T) is allowed } (&ty::Dynamic(from_traits, _, _from_kind), &ty::Dynamic(to_traits, _, _to_kind)) => { + // FIXME(dyn-star): Do the right thing with DynKinds for (from, to) in from_traits.iter().zip(to_traits) { let from = fx.tcx.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), from); diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 7cee9ea3e1d..a6b226ef720 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -367,7 +367,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx.ret(llval); } - #[tracing::instrument(level = "debug", skip(self, helper, bx))] + #[tracing::instrument(level = "trace", skip(self, helper, bx))] fn codegen_drop_terminator( &mut self, helper: TerminatorCodegenHelper<'tcx>, diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index 5301266b824..cbe98548025 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -113,11 +113,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { if let ty::Dynamic(data, _, ty::DynStar) = cast_ty.kind() { // Initial cast from sized to dyn trait let vtable = self.get_vtable_ptr(src.layout.ty, data.principal())?; - let ptr = self.read_immediate(src)?.to_scalar(); - // FIXME(dyn-star): This should not use new_dyn_trait, but - // it does exactly the same thing (makes a scalar pair)... - // so maybe we should just duplicate/rename the function. - let val = Immediate::new_dyn_trait(ptr, vtable, &*self.tcx); + let vtable = Scalar::from_maybe_pointer(vtable, self); + let data = self.read_immediate(src)?.to_scalar(); + let _assert_pointer_sized = data.to_pointer(self)?; + let val = Immediate::ScalarPair(data, vtable); self.write_immediate(val, dest)?; } else { bug!() @@ -327,7 +326,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let new_vptr = self.get_vtable_ptr(ty, data_b.principal())?; self.write_immediate(Immediate::new_dyn_trait(old_data, new_vptr, self), dest) } - (_, &ty::Dynamic(ref data, _, _repr)) => { + (_, &ty::Dynamic(ref data, _, ty::Dyn)) => { // Initial cast from sized to dyn trait let vtable = self.get_vtable_ptr(src_pointee_ty, data.principal())?; let ptr = self.read_scalar(src)?; diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index 1c4c7e7079d..4aa98cb13d8 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -570,7 +570,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } } CastKind::DynStar => { - // FIXME: make sure nothing needs to be done here. + // FIXME(dyn-star): make sure nothing needs to be done here. } // Nothing to check here CastKind::PointerFromExposedAddress diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 72f7064b6ca..d5ec5feffa7 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -381,7 +381,7 @@ declare_features! ( /// Allows `#[doc(masked)]`. (active, doc_masked, "1.21.0", Some(44027), None), /// Allows `dyn* Trait` objects. - (active, dyn_star, "1.65.0", Some(91611), None), + (incomplete, dyn_star, "CURRENT_RUSTC_VERSION", Some(91611), None), /// Allows `X..Y` patterns. (active, exclusive_range_pattern, "1.11.0", Some(37854), None), /// Allows exhaustive pattern matching on types that contain uninhabited types. diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index b8c4534307c..042eeec3f46 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -626,11 +626,11 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { } ty::Dynamic(_, _, ty::DynStar) => { - let mut pointer = scalar_unit(Int(dl.ptr_sized_integer(), false)); - pointer.valid_range_mut().start = 1; + let mut data = scalar_unit(Int(dl.ptr_sized_integer(), false)); + data.valid_range_mut().start = 0; let mut vtable = scalar_unit(Pointer); vtable.valid_range_mut().start = 1; - tcx.intern_layout(self.scalar_pair(pointer, vtable)) + tcx.intern_layout(self.scalar_pair(data, vtable)) } // Arrays and slices. @@ -2474,8 +2474,7 @@ where match tcx.struct_tail_erasing_lifetimes(pointee, cx.param_env()).kind() { ty::Slice(_) | ty::Str => TyMaybeWithLayout::Ty(tcx.types.usize), - // FIXME(eholk): Do the right thing with trait object representation - ty::Dynamic(_, _, _repr) => { + ty::Dynamic(_, _, ty::Dyn) => { TyMaybeWithLayout::Ty(tcx.mk_imm_ref( tcx.lifetimes.re_static, tcx.mk_array(tcx.types.usize, 3), @@ -3379,7 +3378,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { Ok(self.tcx.arena.alloc(fn_abi)) } - #[tracing::instrument(level = "debug", skip(self))] + #[tracing::instrument(level = "trace", skip(self))] fn fn_abi_adjust_for_abi( &self, fn_abi: &mut FnAbi<'tcx, Ty<'tcx>>, diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 4e7eba2d02f..2a843ab0b8b 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -699,7 +699,9 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { // This could also be a different Unsize instruction, like // from a fixed sized array to a slice. But we are only // interested in things that produce a vtable. - if (target_ty.is_trait() || target_ty.is_dyn_star()) && !source_ty.is_trait() { + if (target_ty.is_trait() && !source_ty.is_trait()) + || (target_ty.is_dyn_star() && !source_ty.is_dyn_star()) + { create_mono_items_for_vtable_methods( self.tcx, target_ty, diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index ffe3618bc49..b47f0c09783 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -579,9 +579,7 @@ impl<'a> Parser<'a> { self.bump(); // `dyn` // parse dyn* types - let dyn_star = matches!(self.token.kind, TokenKind::BinOp(token::Star)); - let syntax = if dyn_star { - self.bump(); // `*` + let syntax = if self.eat(&TokenKind::BinOp(token::Star)) { TraitObjectSyntax::DynStar } else { TraitObjectSyntax::Dyn diff --git a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs index 7621ba571fd..aa65a72ab64 100644 --- a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs +++ b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs @@ -627,10 +627,13 @@ fn encode_ty<'tcx>( } // Trait types - ty::Dynamic(predicates, region, _repr) => { + ty::Dynamic(predicates, region, kind) => { // u3dynIE, where is , as // vendor extended type. - let mut s = String::from("u3dynI"); + let mut s = String::from(match kind { + ty::Dyn => "u3dynI", + ty::DynStar => "u7dynstarI", + }); s.push_str(&encode_predicates(tcx, predicates, dict, options)); s.push_str(&encode_region(tcx, *region, dict, options)); s.push('E'); diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index cedc87f5e2b..79d0ef69ba7 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -479,8 +479,12 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { })?; } - ty::Dynamic(predicates, r, _repr) => { - self.push("D"); + ty::Dynamic(predicates, r, kind) => { + self.push(match kind { + ty::Dyn => "D", + // FIXME(dyn-star): need to update v0 mangling docs + ty::DynStar => "D*", + }); self = self.print_dyn_existential(predicates)?; self = r.print(self)?; } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index e1d548323bf..bd73ec47160 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -1067,7 +1067,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { self_ty: Ty<'tcx>, object_ty: Ty<'tcx>, ) { - let ty::Dynamic(predicates, _, _) = object_ty.kind() else { return; }; + let ty::Dynamic(predicates, _, ty::Dyn) = object_ty.kind() else { return; }; let self_ref_ty = self.tcx.mk_imm_ref(self.tcx.lifetimes.re_erased, self_ty); for predicate in predicates.iter() { @@ -1365,7 +1365,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { let trait_pred = self.resolve_vars_if_possible(trait_pred); let ty = trait_pred.skip_binder().self_ty(); let is_object_safe = match ty.kind() { - ty::Dynamic(predicates, _, _) => { + ty::Dynamic(predicates, _, ty::Dyn) => { // If the `dyn Trait` is not object safe, do not suggest `Box`. predicates .principal_def_id() diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 158b00e275e..43c4ddd3f6f 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -890,9 +890,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let mut nested = vec![]; match (source.kind(), target.kind()) { // Trait+Kx+'a -> Trait+Ky+'b (auto traits and lifetime subtyping). - (&ty::Dynamic(ref data_a, r_a, repr_a), &ty::Dynamic(ref data_b, r_b, repr_b)) - if repr_a == repr_b => - { + (&ty::Dynamic(ref data_a, r_a, ty::Dyn), &ty::Dynamic(ref data_b, r_b, ty::Dyn)) => { // See `assemble_candidates_for_unsizing` for more info. // We already checked the compatibility of auto traits within `assemble_candidates_for_unsizing`. let iter = data_a @@ -911,7 +909,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .map(ty::Binder::dummy), ); let existential_predicates = tcx.mk_poly_existential_predicates(iter); - let source_trait = tcx.mk_dynamic(existential_predicates, r_b, repr_b); + let source_trait = tcx.mk_dynamic(existential_predicates, r_b, ty::Dyn); // Require that the traits involved in this upcast are **equal**; // only the **lifetime bound** is changed. @@ -938,7 +936,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } // `T` -> `Trait` - (_, &ty::Dynamic(ref data, r, _repr)) => { + (_, &ty::Dynamic(ref data, r, ty::Dyn)) => { let mut object_dids = data.auto_traits().chain(data.principal_def_id()); if let Some(did) = object_dids.find(|did| !tcx.is_object_safe(*did)) { return Err(TraitNotObjectSafe(did)); diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs index 86da6d7bbd1..45d5ea93d54 100644 --- a/compiler/rustc_traits/src/chalk/lowering.rs +++ b/compiler/rustc_traits/src/chalk/lowering.rs @@ -326,7 +326,8 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Ty>> for Ty<'tcx> { )), }) } - ty::Dynamic(predicates, region, _repr) => chalk_ir::TyKind::Dyn(chalk_ir::DynTy { + // FIXME(dyn-star): handle the dynamic kind (dyn or dyn*) + ty::Dynamic(predicates, region, _kind) => chalk_ir::TyKind::Dyn(chalk_ir::DynTy { bounds: predicates.lower_into(interner), lifetime: region.lower_into(interner), }), diff --git a/compiler/rustc_type_ir/src/sty.rs b/compiler/rustc_type_ir/src/sty.rs index f8090cd9dd8..6d54924e515 100644 --- a/compiler/rustc_type_ir/src/sty.rs +++ b/compiler/rustc_type_ir/src/sty.rs @@ -19,26 +19,33 @@ use rustc_data_structures::stable_hasher::HashStable; use rustc_serialize::{Decodable, Decoder, Encodable}; /// Specifies how a trait object is represented. -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Encodable, Decodable)] +#[derive( + Clone, + Copy, + PartialEq, + Eq, + PartialOrd, + Ord, + Hash, + Debug, + Encodable, + Decodable, + HashStable_Generic +)] pub enum DynKind { /// An unsized `dyn Trait` object Dyn, /// A sized `dyn* Trait` object + /// + /// These objects are represented as a `(data, vtable)` pair where `data` is a ptr-sized value + /// (often a pointer to the real object, but not necessarily) and `vtable` is a pointer to + /// the vtable for `dyn* Trait`. The representation is essentially the same as `&dyn Trait` + /// or similar, but the drop function included in the vtable is responsible for freeing the + /// underlying storage if needed. This allows a `dyn*` object to be treated agnostically with + /// respect to whether it points to a `Box`, `Rc`, etc. DynStar, } -// Manually implemented because deriving HashStable requires rustc_query_system, which would -// create a cyclic dependency. -impl HashStable for DynKind { - fn hash_stable( - &self, - hcx: &mut CTX, - hasher: &mut rustc_data_structures::stable_hasher::StableHasher, - ) { - std::mem::discriminant(self).hash_stable(hcx, hasher); - } -} - /// Defines the kinds of types used by the type system. /// /// Types written by the user start out as `hir::TyKind` and get diff --git a/compiler/rustc_typeck/src/check/cast.rs b/compiler/rustc_typeck/src/check/cast.rs index 640aa8c65ed..81a979865ac 100644 --- a/compiler/rustc_typeck/src/check/cast.rs +++ b/compiler/rustc_typeck/src/check/cast.rs @@ -105,7 +105,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Ok(match *t.kind() { ty::Slice(_) | ty::Str => Some(PointerKind::Length), - ty::Dynamic(ref tty, ..) => Some(PointerKind::VTable(tty.principal_def_id())), + ty::Dynamic(ref tty, _, ty::Dyn) => Some(PointerKind::VTable(tty.principal_def_id())), ty::Adt(def, substs) if def.is_struct() => match def.non_enum_variant().fields.last() { None => Some(PointerKind::Thin), Some(f) => { @@ -142,6 +142,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | ty::Generator(..) | ty::Adt(..) | ty::Never + | ty::Dynamic(_, _, ty::DynStar) | ty::Error(_) => { let reported = self .tcx @@ -246,7 +247,7 @@ fn check_dyn_star_cast<'tcx>( let cause = ObligationCause::new( expr.span, fcx.body_id, - // FIXME: Use a better obligation cause code + // FIXME(dyn-star): Use a better obligation cause code ObligationCauseCode::MiscObligation, ); @@ -927,10 +928,10 @@ impl<'a, 'tcx> CastCheck<'tcx> { (Int(_) | Float, Int(_) | Float) => Ok(CastKind::NumericCast), - // FIXME: this needs more conditions... + // FIXME(dyn-star): this needs more conditions... (_, DynStar) => Ok(CastKind::DynStarCast), - // FIXME: do we want to allow dyn* upcasting or other casts? + // FIXME(dyn-star): do we want to allow dyn* upcasting or other casts? (DynStar, _) => Err(CastError::IllegalCast), } } diff --git a/src/test/ui/dyn-star/const.rs b/src/test/ui/dyn-star/const.rs index 29a1a0d0253..e49caf649f8 100644 --- a/src/test/ui/dyn-star/const.rs +++ b/src/test/ui/dyn-star/const.rs @@ -1,6 +1,6 @@ // run-pass #![feature(dyn_star)] -#![allow(unused)] +#![allow(unused, incomplete_features)] use std::fmt::Debug; diff --git a/src/test/ui/dyn-star/drop.rs b/src/test/ui/dyn-star/drop.rs index 2ce77593777..46b232f3dd3 100644 --- a/src/test/ui/dyn-star/drop.rs +++ b/src/test/ui/dyn-star/drop.rs @@ -1,6 +1,7 @@ // run-pass // check-run-results #![feature(dyn_star)] +#![allow(incomplete_features)] use std::fmt::Debug; diff --git a/src/test/ui/dyn-star/error.rs b/src/test/ui/dyn-star/error.rs index 81f7f39ae13..33eff80a5fe 100644 --- a/src/test/ui/dyn-star/error.rs +++ b/src/test/ui/dyn-star/error.rs @@ -1,4 +1,5 @@ #![feature(dyn_star)] +#![allow(incomplete_features)] use std::fmt::Debug; diff --git a/src/test/ui/dyn-star/error.stderr b/src/test/ui/dyn-star/error.stderr index 92ae2780d29..d612ccc630e 100644 --- a/src/test/ui/dyn-star/error.stderr +++ b/src/test/ui/dyn-star/error.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `{integer}: Foo` is not satisfied - --> $DIR/error.rs:9:27 + --> $DIR/error.rs:10:27 | LL | let dyn_i: dyn* Foo = i as dyn* Foo; | ^ the trait `Foo` is not implemented for `{integer}` diff --git a/src/test/ui/dyn-star/make-dyn-star.rs b/src/test/ui/dyn-star/make-dyn-star.rs index b0b8f07abe5..708ffa25d6f 100644 --- a/src/test/ui/dyn-star/make-dyn-star.rs +++ b/src/test/ui/dyn-star/make-dyn-star.rs @@ -1,5 +1,6 @@ // run-pass #![feature(dyn_star)] +#![allow(incomplete_features)] use std::fmt::Debug; diff --git a/src/test/ui/dyn-star/method.rs b/src/test/ui/dyn-star/method.rs index 4d32db034a4..d04958ca2aa 100644 --- a/src/test/ui/dyn-star/method.rs +++ b/src/test/ui/dyn-star/method.rs @@ -1,5 +1,6 @@ // run-pass #![feature(dyn_star)] +#![allow(incomplete_features)] trait Foo { fn get(&self) -> usize; diff --git a/src/test/ui/dyn-star/syntax.rs b/src/test/ui/dyn-star/syntax.rs index 7848996e5e0..618c72562b2 100644 --- a/src/test/ui/dyn-star/syntax.rs +++ b/src/test/ui/dyn-star/syntax.rs @@ -3,6 +3,7 @@ // check-pass #![feature(dyn_star)] +#![allow(incomplete_features)] pub fn dyn_star_parameter(_: dyn* Send) { } diff --git a/src/tools/clippy/clippy_lints/src/transmute/utils.rs b/src/tools/clippy/clippy_lints/src/transmute/utils.rs index 78cc589cc29..8bdadf24402 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/utils.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/utils.rs @@ -2,18 +2,11 @@ use rustc_hir::Expr; use rustc_lint::LateContext; use rustc_middle::ty::{cast::CastKind, Ty}; use rustc_span::DUMMY_SP; -use rustc_typeck::check::{ - cast::{self, CastCheckResult}, - FnCtxt, Inherited, -}; +use rustc_typeck::check::{cast::{self, CastCheckResult}, FnCtxt, Inherited}; // check if the component types of the transmuted collection and the result have different ABI, // size or alignment -pub(super) fn is_layout_incompatible<'tcx>( - cx: &LateContext<'tcx>, - from: Ty<'tcx>, - to: Ty<'tcx>, -) -> bool { +pub(super) fn is_layout_incompatible<'tcx>(cx: &LateContext<'tcx>, from: Ty<'tcx>, to: Ty<'tcx>) -> bool { if let Ok(from) = cx.tcx.try_normalize_erasing_regions(cx.param_env, from) && let Ok(to) = cx.tcx.try_normalize_erasing_regions(cx.param_env, to) && let Ok(from_layout) = cx.tcx.layout_of(cx.param_env.and(from)) @@ -36,9 +29,7 @@ pub(super) fn can_be_expressed_as_pointer_cast<'tcx>( from_ty: Ty<'tcx>, to_ty: Ty<'tcx>, ) -> bool { - use CastKind::{ - AddrPtrCast, ArrayPtrCast, FnPtrAddrCast, FnPtrPtrCast, PtrAddrCast, PtrPtrCast, - }; + use CastKind::{AddrPtrCast, ArrayPtrCast, FnPtrAddrCast, FnPtrPtrCast, PtrAddrCast, PtrPtrCast}; matches!( check_cast(cx, e, from_ty, to_ty), Some(PtrPtrCast | PtrAddrCast | AddrPtrCast | ArrayPtrCast | FnPtrPtrCast | FnPtrAddrCast) @@ -49,12 +40,7 @@ pub(super) fn can_be_expressed_as_pointer_cast<'tcx>( /// the cast. In certain cases, including some invalid casts from array references /// to pointers, this may cause additional errors to be emitted and/or ICE error /// messages. This function will panic if that occurs. -fn check_cast<'tcx>( - cx: &LateContext<'tcx>, - e: &'tcx Expr<'_>, - from_ty: Ty<'tcx>, - to_ty: Ty<'tcx>, -) -> Option { +fn check_cast<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, from_ty: Ty<'tcx>, to_ty: Ty<'tcx>) -> Option { let hir_id = e.hir_id; let local_def_id = hir_id.owner; @@ -62,7 +48,10 @@ fn check_cast<'tcx>( let fn_ctxt = FnCtxt::new(&inherited, cx.param_env, hir_id); // If we already have errors, we can't be sure we can pointer cast. - assert!(!fn_ctxt.errors_reported_since_creation(), "Newly created FnCtxt contained errors"); + assert!( + !fn_ctxt.errors_reported_since_creation(), + "Newly created FnCtxt contained errors" + ); if let CastCheckResult::Deferred(check) = cast::check_cast( &fn_ctxt, e, from_ty, to_ty, diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index 781744870cb..8835b932909 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -18,11 +18,7 @@ use std::borrow::Cow; type McfResult = Result<(), (Span, Cow<'static, str>)>; -pub fn is_min_const_fn<'a, 'tcx>( - tcx: TyCtxt<'tcx>, - body: &'a Body<'tcx>, - msrv: Option, -) -> McfResult { +pub fn is_min_const_fn<'a, 'tcx>(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, msrv: Option) -> McfResult { let def_id = body.source.def_id(); let mut current = def_id; loop { @@ -37,18 +33,10 @@ pub fn is_min_const_fn<'a, 'tcx>( | ty::PredicateKind::ConstEquate(..) | ty::PredicateKind::Trait(..) | ty::PredicateKind::TypeWellFormedFromEnv(..) => continue, - ty::PredicateKind::ObjectSafe(_) => { - panic!("object safe predicate on function: {:#?}", predicate) - } - ty::PredicateKind::ClosureKind(..) => { - panic!("closure kind predicate on function: {:#?}", predicate) - } - ty::PredicateKind::Subtype(_) => { - panic!("subtype predicate on function: {:#?}", predicate) - } - ty::PredicateKind::Coerce(_) => { - panic!("coerce predicate on function: {:#?}", predicate) - } + ty::PredicateKind::ObjectSafe(_) => panic!("object safe predicate on function: {:#?}", predicate), + ty::PredicateKind::ClosureKind(..) => panic!("closure kind predicate on function: {:#?}", predicate), + ty::PredicateKind::Subtype(_) => panic!("subtype predicate on function: {:#?}", predicate), + ty::PredicateKind::Coerce(_) => panic!("coerce predicate on function: {:#?}", predicate), } } match predicates.parent { @@ -89,23 +77,22 @@ fn check_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span) -> McfResult { match ty.kind() { ty::Ref(_, _, hir::Mutability::Mut) => { return Err((span, "mutable references in const fn are unstable".into())); - } + }, ty::Opaque(..) => return Err((span, "`impl Trait` in const fn is unstable".into())), ty::FnPtr(..) => { return Err((span, "function pointers in const fn are unstable".into())); - } + }, ty::Dynamic(preds, _, _) => { for pred in preds.iter() { match pred.skip_binder() { - ty::ExistentialPredicate::AutoTrait(_) - | ty::ExistentialPredicate::Projection(_) => { + ty::ExistentialPredicate::AutoTrait(_) | ty::ExistentialPredicate::Projection(_) => { return Err(( span, "trait bounds other than `Sized` \ on const fn parameters are unstable" .into(), )); - } + }, ty::ExistentialPredicate::Trait(trait_ref) => { if Some(trait_ref.def_id) != tcx.lang_items().sized_trait() { return Err(( @@ -115,11 +102,11 @@ fn check_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span) -> McfResult { .into(), )); } - } + }, } } - } - _ => {} + }, + _ => {}, } } Ok(()) @@ -133,13 +120,10 @@ fn check_rvalue<'tcx>( span: Span, ) -> McfResult { match rvalue { - Rvalue::ThreadLocalRef(_) => { - Err((span, "cannot access thread local storage in const fn".into())) - } - Rvalue::Len(place) - | Rvalue::Discriminant(place) - | Rvalue::Ref(_, _, place) - | Rvalue::AddressOf(_, place) => check_place(tcx, *place, span, body), + Rvalue::ThreadLocalRef(_) => Err((span, "cannot access thread local storage in const fn".into())), + Rvalue::Len(place) | Rvalue::Discriminant(place) | Rvalue::Ref(_, _, place) | Rvalue::AddressOf(_, place) => { + check_place(tcx, *place, span, body) + }, Rvalue::CopyForDeref(place) => check_place(tcx, *place, span, body), Rvalue::Repeat(operand, _) | Rvalue::Use(operand) @@ -152,9 +136,7 @@ fn check_rvalue<'tcx>( ) => check_operand(tcx, operand, span, body), Rvalue::Cast( CastKind::Pointer( - PointerCast::UnsafeFnPointer - | PointerCast::ClosureFnPointer(_) - | PointerCast::ReifyFnPointer, + PointerCast::UnsafeFnPointer | PointerCast::ClosureFnPointer(_) | PointerCast::ReifyFnPointer, ), _, _, @@ -164,10 +146,7 @@ fn check_rvalue<'tcx>( deref_ty.ty } else { // We cannot allow this for now. - return Err(( - span, - "unsizing casts are only allowed for references right now".into(), - )); + return Err((span, "unsizing casts are only allowed for references right now".into())); }; let unsized_ty = tcx.struct_tail_erasing_lifetimes(pointee_ty, tcx.param_env(def_id)); if let ty::Slice(_) | ty::Str = unsized_ty.kind() { @@ -178,14 +157,14 @@ fn check_rvalue<'tcx>( // We just can't allow trait objects until we have figured out trait method calls. Err((span, "unsizing casts are not allowed in const fn".into())) } - } + }, Rvalue::Cast(CastKind::PointerExposeAddress, _, _) => { Err((span, "casting pointers to ints is unstable in const fn".into())) - } + }, Rvalue::Cast(CastKind::DynStar, _, _) => { // FIXME(dyn-star) unimplemented!() - } + }, // binops are fine on integers Rvalue::BinaryOp(_, box (lhs, rhs)) | Rvalue::CheckedBinaryOp(_, box (lhs, rhs)) => { check_operand(tcx, lhs, span, body)?; @@ -194,12 +173,13 @@ fn check_rvalue<'tcx>( if ty.is_integral() || ty.is_bool() || ty.is_char() { Ok(()) } else { - Err((span, "only int, `bool` and `char` operations are stable in const fn".into())) + Err(( + span, + "only int, `bool` and `char` operations are stable in const fn".into(), + )) } - } - Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) | Rvalue::ShallowInitBox(_, _) => { - Ok(()) - } + }, + Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) | Rvalue::ShallowInitBox(_, _) => Ok(()), Rvalue::UnaryOp(_, operand) => { let ty = operand.ty(body, tcx); if ty.is_integral() || ty.is_bool() { @@ -207,13 +187,13 @@ fn check_rvalue<'tcx>( } else { Err((span, "only int and `bool` operations are stable in const fn".into())) } - } + }, Rvalue::Aggregate(_, operands) => { for operand in operands { check_operand(tcx, operand, span, body)?; } Ok(()) - } + }, } } @@ -228,7 +208,7 @@ fn check_statement<'tcx>( StatementKind::Assign(box (place, rval)) => { check_place(tcx, *place, span, body)?; check_rvalue(tcx, body, def_id, rval, span) - } + }, StatementKind::FakeRead(box (_, place)) => check_place(tcx, *place, span, body), // just an assignment @@ -238,15 +218,13 @@ fn check_statement<'tcx>( StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(op)) => check_operand(tcx, op, span, body), - StatementKind::CopyNonOverlapping(box rustc_middle::mir::CopyNonOverlapping { - dst, - src, - count, - }) => { + StatementKind::Intrinsic(box NonDivergingIntrinsic::CopyNonOverlapping( + rustc_middle::mir::CopyNonOverlapping { dst, src, count }, + )) => { check_operand(tcx, dst, span, body)?; check_operand(tcx, src, span, body)?; check_operand(tcx, count, span, body) - } + }, // These are all NOPs StatementKind::StorageLive(_) | StatementKind::StorageDead(_) @@ -257,12 +235,7 @@ fn check_statement<'tcx>( } } -fn check_operand<'tcx>( - tcx: TyCtxt<'tcx>, - operand: &Operand<'tcx>, - span: Span, - body: &Body<'tcx>, -) -> McfResult { +fn check_operand<'tcx>(tcx: TyCtxt<'tcx>, operand: &Operand<'tcx>, span: Span, body: &Body<'tcx>) -> McfResult { match operand { Operand::Move(place) | Operand::Copy(place) => check_place(tcx, *place, span, body), Operand::Constant(c) => match c.check_static_ptr(tcx) { @@ -272,12 +245,7 @@ fn check_operand<'tcx>( } } -fn check_place<'tcx>( - tcx: TyCtxt<'tcx>, - place: Place<'tcx>, - span: Span, - body: &Body<'tcx>, -) -> McfResult { +fn check_place<'tcx>(tcx: TyCtxt<'tcx>, place: Place<'tcx>, span: Span, body: &Body<'tcx>) -> McfResult { let mut cursor = place.projection.as_ref(); while let [ref proj_base @ .., elem] = *cursor { cursor = proj_base; @@ -290,12 +258,12 @@ fn check_place<'tcx>( return Err((span, "accessing union fields is unstable".into())); } } - } + }, ProjectionElem::ConstantIndex { .. } | ProjectionElem::Downcast(..) | ProjectionElem::Subslice { .. } | ProjectionElem::Deref - | ProjectionElem::Index(_) => {} + | ProjectionElem::Index(_) => {}, } } @@ -321,16 +289,18 @@ fn check_terminator<'a, 'tcx>( TerminatorKind::DropAndReplace { place, value, .. } => { check_place(tcx, *place, span, body)?; check_operand(tcx, value, span, body) - } + }, - TerminatorKind::SwitchInt { discr, switch_ty: _, targets: _ } => { - check_operand(tcx, discr, span, body) - } + TerminatorKind::SwitchInt { + discr, + switch_ty: _, + targets: _, + } => check_operand(tcx, discr, span, body), TerminatorKind::Abort => Err((span, "abort is not stable in const fn".into())), TerminatorKind::GeneratorDrop | TerminatorKind::Yield { .. } => { Err((span, "const fn generators are unstable".into())) - } + }, TerminatorKind::Call { func, @@ -375,15 +345,17 @@ fn check_terminator<'a, 'tcx>( } else { Err((span, "can only call other const fns within const fn".into())) } - } + }, - TerminatorKind::Assert { cond, expected: _, msg: _, target: _, cleanup: _ } => { - check_operand(tcx, cond, span, body) - } + TerminatorKind::Assert { + cond, + expected: _, + msg: _, + target: _, + cleanup: _, + } => check_operand(tcx, cond, span, body), - TerminatorKind::InlineAsm { .. } => { - Err((span, "cannot use inline assembly in const fn".into())) - } + TerminatorKind::InlineAsm { .. } => Err((span, "cannot use inline assembly in const fn".into())), } } diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index 99803ae93a7..a8ad6cf4f6a 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -14,9 +14,8 @@ use rustc_lint::LateContext; use rustc_middle::mir::interpret::{ConstValue, Scalar}; use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst}; use rustc_middle::ty::{ - self, AdtDef, Binder, BoundRegion, DefIdTree, FnSig, IntTy, ParamEnv, Predicate, PredicateKind, - ProjectionTy, Region, RegionKind, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, - UintTy, VariantDef, VariantDiscr, + self, AdtDef, Binder, BoundRegion, DefIdTree, FnSig, IntTy, ParamEnv, Predicate, PredicateKind, ProjectionTy, + Region, RegionKind, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, UintTy, VariantDef, VariantDiscr, }; use rustc_span::symbol::Ident; use rustc_span::{sym, Span, Symbol, DUMMY_SP}; @@ -167,7 +166,9 @@ pub fn implements_trait_with_env<'tcx>( } let ty_params = tcx.mk_substs(ty_params.iter()); tcx.infer_ctxt().enter(|infcx| { - infcx.type_implements_trait(trait_id, ty, ty_params, param_env).must_apply_modulo_regions() + infcx + .type_implements_trait(trait_id, ty, ty_params, param_env) + .must_apply_modulo_regions() }) } @@ -184,14 +185,11 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { match ty.kind() { ty::Adt(adt, _) => cx.tcx.has_attr(adt.did(), sym::must_use), ty::Foreign(did) => cx.tcx.has_attr(*did, sym::must_use), - ty::Slice(ty) - | ty::Array(ty, _) - | ty::RawPtr(ty::TypeAndMut { ty, .. }) - | ty::Ref(_, ty, _) => { + ty::Slice(ty) | ty::Array(ty, _) | ty::RawPtr(ty::TypeAndMut { ty, .. }) | ty::Ref(_, ty, _) => { // for the Array case we don't need to care for the len == 0 case // because we don't want to lint functions returning empty arrays is_must_use_ty(cx, *ty) - } + }, ty::Tuple(substs) => substs.iter().any(|ty| is_must_use_ty(cx, ty)), ty::Opaque(def_id, _) => { for (predicate, _) in cx.tcx.explicit_item_bounds(*def_id) { @@ -202,7 +200,7 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { } } false - } + }, ty::Dynamic(binder, _, _) => { for predicate in binder.iter() { if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder() { @@ -212,7 +210,7 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { } } false - } + }, _ => false, } } @@ -222,11 +220,7 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { // not succeed /// Checks if `Ty` is normalizable. This function is useful /// to avoid crashes on `layout_of`. -pub fn is_normalizable<'tcx>( - cx: &LateContext<'tcx>, - param_env: ty::ParamEnv<'tcx>, - ty: Ty<'tcx>, -) -> bool { +pub fn is_normalizable<'tcx>(cx: &LateContext<'tcx>, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool { is_normalizable_helper(cx, param_env, ty, &mut FxHashMap::default()) } @@ -246,14 +240,15 @@ fn is_normalizable_helper<'tcx>( if infcx.at(&cause, param_env).normalize(ty).is_ok() { match ty.kind() { ty::Adt(def, substs) => def.variants().iter().all(|variant| { - variant.fields.iter().all(|field| { - is_normalizable_helper(cx, param_env, field.ty(cx.tcx, substs), cache) - }) + variant + .fields + .iter() + .all(|field| is_normalizable_helper(cx, param_env, field.ty(cx.tcx, substs), cache)) }), _ => ty.walk().all(|generic_arg| match generic_arg.unpack() { GenericArgKind::Type(inner_ty) if inner_ty != ty => { is_normalizable_helper(cx, param_env, inner_ty, cache) - } + }, _ => true, // if inner_ty == ty, we've already checked it }), } @@ -278,9 +273,7 @@ pub fn is_recursively_primitive_type(ty: Ty<'_>) -> bool { match *ty.kind() { ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str => true, ty::Ref(_, inner, _) if *inner.kind() == ty::Str => true, - ty::Array(inner_type, _) | ty::Slice(inner_type) => { - is_recursively_primitive_type(inner_type) - } + ty::Array(inner_type, _) | ty::Slice(inner_type) => is_recursively_primitive_type(inner_type), ty::Tuple(inner_types) => inner_types.iter().all(is_recursively_primitive_type), _ => false, } @@ -320,9 +313,11 @@ pub fn is_type_diagnostic_item(cx: &LateContext<'_>, ty: Ty<'_>, diag_item: Symb /// Returns `false` if the `LangItem` is not defined. pub fn is_type_lang_item(cx: &LateContext<'_>, ty: Ty<'_>, lang_item: hir::LangItem) -> bool { match ty.kind() { - ty::Adt(adt, _) => { - cx.tcx.lang_items().require(lang_item).map_or(false, |li| li == adt.did()) - } + ty::Adt(adt, _) => cx + .tcx + .lang_items() + .require(lang_item) + .map_or(false, |li| li == adt.did()), _ => false, } } @@ -347,11 +342,7 @@ pub fn match_type(cx: &LateContext<'_>, ty: Ty<'_>, path: &[&str]) -> bool { /// deallocate memory. For these types, and composites containing them, changing the drop order /// won't result in any observable side effects. pub fn needs_ordered_drop<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { - fn needs_ordered_drop_inner<'tcx>( - cx: &LateContext<'tcx>, - ty: Ty<'tcx>, - seen: &mut FxHashSet>, - ) -> bool { + fn needs_ordered_drop_inner<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, seen: &mut FxHashSet>) -> bool { if !seen.insert(ty) { return false; } @@ -402,7 +393,11 @@ pub fn needs_ordered_drop<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { /// removed. pub fn peel_mid_ty_refs(ty: Ty<'_>) -> (Ty<'_>, usize) { fn peel(ty: Ty<'_>, count: usize) -> (Ty<'_>, usize) { - if let ty::Ref(_, ty, _) = ty.kind() { peel(*ty, count + 1) } else { (ty, count) } + if let ty::Ref(_, ty, _) = ty.kind() { + peel(*ty, count + 1) + } else { + (ty, count) + } } peel(ty, 0) } @@ -457,18 +452,17 @@ pub fn same_type_and_consts<'tcx>(a: Ty<'tcx>, b: Ty<'tcx>) -> bool { return false; } - substs_a.iter().zip(substs_b.iter()).all(|(arg_a, arg_b)| { - match (arg_a.unpack(), arg_b.unpack()) { - (GenericArgKind::Const(inner_a), GenericArgKind::Const(inner_b)) => { - inner_a == inner_b - } + substs_a + .iter() + .zip(substs_b.iter()) + .all(|(arg_a, arg_b)| match (arg_a.unpack(), arg_b.unpack()) { + (GenericArgKind::Const(inner_a), GenericArgKind::Const(inner_b)) => inner_a == inner_b, (GenericArgKind::Type(type_a), GenericArgKind::Type(type_b)) => { same_type_and_consts(type_a, type_b) - } + }, _ => true, - } - }) - } + }) + }, _ => a == b, } } @@ -484,10 +478,7 @@ pub fn is_uninit_value_valid_for_ty(cx: &LateContext<'_>, ty: Ty<'_>) -> bool { } /// Gets an iterator over all predicates which apply to the given item. -pub fn all_predicates_of( - tcx: TyCtxt<'_>, - id: DefId, -) -> impl Iterator, Span)> { +pub fn all_predicates_of(tcx: TyCtxt<'_>, id: DefId) -> impl Iterator, Span)> { let mut next_id = Some(id); iter::from_fn(move || { next_id.take().map(|id| { @@ -517,7 +508,7 @@ impl<'tcx> ExprFnSig<'tcx> { } else { Some(sig.input(i)) } - } + }, Self::Closure(_, sig) => Some(sig.input(0).map_bound(|ty| ty.tuple_fields()[i])), Self::Trait(inputs, _, _) => Some(inputs.map_bound(|ty| ty.tuple_fields()[i])), } @@ -526,10 +517,7 @@ impl<'tcx> ExprFnSig<'tcx> { /// Gets the argument type at the given offset. For closures this will also get the type as /// written. This will return `None` when the index is out of bounds only for variadic /// functions, otherwise this will panic. - pub fn input_with_hir( - self, - i: usize, - ) -> Option<(Option<&'tcx hir::Ty<'tcx>>, Binder<'tcx, Ty<'tcx>>)> { + pub fn input_with_hir(self, i: usize) -> Option<(Option<&'tcx hir::Ty<'tcx>>, Binder<'tcx, Ty<'tcx>>)> { match self { Self::Sig(sig, _) => { if sig.c_variadic() { @@ -540,7 +528,7 @@ impl<'tcx> ExprFnSig<'tcx> { } else { Some((None, sig.input(i))) } - } + }, Self::Closure(decl, sig) => Some(( decl.and_then(|decl| decl.inputs.get(i)), sig.input(0).map_bound(|ty| ty.tuple_fields()[i]), @@ -559,15 +547,17 @@ impl<'tcx> ExprFnSig<'tcx> { } pub fn predicates_id(&self) -> Option { - if let ExprFnSig::Sig(_, id) | ExprFnSig::Trait(_, _, id) = *self { id } else { None } + if let ExprFnSig::Sig(_, id) | ExprFnSig::Trait(_, _, id) = *self { + id + } else { + None + } } } /// If the expression is function like, get the signature for it. pub fn expr_sig<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>) -> Option> { - if let Res::Def(DefKind::Fn | DefKind::Ctor(_, CtorKind::Fn) | DefKind::AssocFn, id) = - path_res(cx, expr) - { + if let Res::Def(DefKind::Fn | DefKind::Ctor(_, CtorKind::Fn) | DefKind::AssocFn, id) = path_res(cx, expr) { Some(ExprFnSig::Sig(cx.tcx.fn_sig(id), Some(id))) } else { ty_sig(cx, cx.typeck_results().expr_ty_adjusted(expr).peel_refs()) @@ -581,14 +571,12 @@ pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option { - let decl = id.as_local().and_then(|id| { - cx.tcx.hir().fn_decl_by_hir_id(cx.tcx.hir().local_def_id_to_hir_id(id)) - }); + let decl = id + .as_local() + .and_then(|id| cx.tcx.hir().fn_decl_by_hir_id(cx.tcx.hir().local_def_id_to_hir_id(id))); Some(ExprFnSig::Closure(decl, subs.as_closure().sig())) - } - ty::FnDef(id, subs) => { - Some(ExprFnSig::Sig(cx.tcx.bound_fn_sig(id).subst(cx.tcx, subs), Some(id))) - } + }, + ty::FnDef(id, subs) => Some(ExprFnSig::Sig(cx.tcx.bound_fn_sig(id).subst(cx.tcx, subs), Some(id))), ty::Opaque(id, _) => sig_from_bounds(cx, ty, cx.tcx.item_bounds(id), cx.tcx.opt_parent(id)), ty::FnPtr(sig) => Some(ExprFnSig::Sig(sig, None)), ty::Dynamic(bounds, _, _) => { @@ -601,19 +589,16 @@ pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option None, } - } + }, ty::Projection(proj) => match cx.tcx.try_normalize_erasing_regions(cx.param_env, ty) { Ok(normalized_ty) if normalized_ty != ty => ty_sig(cx, normalized_ty), - _ => sig_for_projection(cx, proj) - .or_else(|| sig_from_bounds(cx, ty, cx.param_env.caller_bounds(), None)), + _ => sig_for_projection(cx, proj).or_else(|| sig_from_bounds(cx, ty, cx.param_env.caller_bounds(), None)), }, ty::Param(_) => sig_from_bounds(cx, ty, cx.param_env.caller_bounds(), None), _ => None, @@ -644,7 +629,7 @@ fn sig_from_bounds<'tcx>( return None; } inputs = Some(i); - } + }, PredicateKind::Projection(p) if Some(p.projection_ty.item_def_id) == lang_items.fn_once_output() && p.projection_ty.self_ty() == ty => @@ -654,7 +639,7 @@ fn sig_from_bounds<'tcx>( return None; } output = Some(pred.kind().rebind(p.term.ty().unwrap())); - } + }, _ => (), } } @@ -662,10 +647,7 @@ fn sig_from_bounds<'tcx>( inputs.map(|ty| ExprFnSig::Trait(ty, output, predicates_id)) } -fn sig_for_projection<'tcx>( - cx: &LateContext<'tcx>, - ty: ProjectionTy<'tcx>, -) -> Option> { +fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: ProjectionTy<'tcx>) -> Option> { let mut inputs = None; let mut output = None; let lang_items = cx.tcx.lang_items(); @@ -691,10 +673,8 @@ fn sig_for_projection<'tcx>( return None; } inputs = Some(i); - } - PredicateKind::Projection(p) - if Some(p.projection_ty.item_def_id) == lang_items.fn_once_output() => - { + }, + PredicateKind::Projection(p) if Some(p.projection_ty.item_def_id) == lang_items.fn_once_output() => { if output.is_some() { // Multiple different fn trait impls. Is this even allowed? return None; @@ -703,7 +683,7 @@ fn sig_for_projection<'tcx>( pred.map_bound(|pred| pred.kind().rebind(p.term.ty().unwrap())) .subst(cx.tcx, ty.substs), ); - } + }, _ => (), } } @@ -797,10 +777,7 @@ pub fn for_each_top_level_late_bound_region( ControlFlow::Continue(()) } } - fn visit_binder>( - &mut self, - t: &Binder<'tcx, T>, - ) -> ControlFlow { + fn visit_binder>(&mut self, t: &Binder<'tcx, T>) -> ControlFlow { self.index += 1; let res = t.super_visit_with(self); self.index -= 1; @@ -814,27 +791,19 @@ pub fn for_each_top_level_late_bound_region( pub fn variant_of_res<'tcx>(cx: &LateContext<'tcx>, res: Res) -> Option<&'tcx VariantDef> { match res { Res::Def(DefKind::Struct, id) => Some(cx.tcx.adt_def(id).non_enum_variant()), - Res::Def(DefKind::Variant, id) => { - Some(cx.tcx.adt_def(cx.tcx.parent(id)).variant_with_id(id)) - } - Res::Def(DefKind::Ctor(CtorOf::Struct, _), id) => { - Some(cx.tcx.adt_def(cx.tcx.parent(id)).non_enum_variant()) - } + Res::Def(DefKind::Variant, id) => Some(cx.tcx.adt_def(cx.tcx.parent(id)).variant_with_id(id)), + Res::Def(DefKind::Ctor(CtorOf::Struct, _), id) => Some(cx.tcx.adt_def(cx.tcx.parent(id)).non_enum_variant()), Res::Def(DefKind::Ctor(CtorOf::Variant, _), id) => { let var_id = cx.tcx.parent(id); Some(cx.tcx.adt_def(cx.tcx.parent(var_id)).variant_with_id(var_id)) - } + }, Res::SelfCtor(id) => Some(cx.tcx.type_of(id).ty_adt_def().unwrap().non_enum_variant()), _ => None, } } /// Checks if the type is a type parameter implementing `FnOnce`, but not `FnMut`. -pub fn ty_is_fn_once_param<'tcx>( - tcx: TyCtxt<'_>, - ty: Ty<'tcx>, - predicates: &'tcx [Predicate<'_>], -) -> bool { +pub fn ty_is_fn_once_param<'tcx>(tcx: TyCtxt<'_>, ty: Ty<'tcx>, predicates: &'tcx [Predicate<'_>]) -> bool { let ty::Param(ty) = *ty.kind() else { return false; };