From a7b4d667feb6149b512da227117baa527529dcaf Mon Sep 17 00:00:00 2001 From: Caio Date: Tue, 1 Mar 2022 18:34:35 -0300 Subject: [PATCH] 9 - Make more use of `let_chains` Continuation of #94376. cc #53667 --- compiler/rustc_trait_selection/src/lib.rs | 9 +- .../src/traits/error_reporting/mod.rs | 90 +++++++++---------- .../src/traits/error_reporting/suggestions.rs | 85 ++++++++---------- .../src/traits/on_unimplemented.rs | 38 ++++---- .../src/traits/query/dropck_outlives.rs | 28 +++--- .../src/traits/relationships.rs | 72 +++++++-------- .../src/traits/select/mod.rs | 34 ++++--- .../rustc_trait_selection/src/traits/wf.rs | 38 ++++---- 8 files changed, 176 insertions(+), 218 deletions(-) diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index 5569334ff3d20..7523b8441013a 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -10,19 +10,20 @@ //! //! This API is completely unstable and subject to change. +#![allow(rustc::potential_query_instability)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(bool_to_option)] #![feature(box_patterns)] -#![feature(drain_filter)] +#![feature(control_flow_enum)] +#![feature(crate_visibility_modifier)] #![feature(derive_default_enum)] +#![feature(drain_filter)] #![feature(hash_drain_filter)] #![feature(label_break_value)] +#![feature(let_chains)] #![feature(let_else)] #![feature(never_type)] -#![feature(crate_visibility_modifier)] -#![feature(control_flow_enum)] #![recursion_limit = "512"] // For rustdoc -#![allow(rustc::potential_query_instability)] #[macro_use] extern crate rustc_macros; diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 82c3f79a4fa7b..8e42a41c8cf61 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1098,42 +1098,43 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { ); } } - if let &[ArgKind::Tuple(_, ref fields)] = &expected_args[..] { - if fields.len() == found_args.len() && is_closure { - let sugg = format!( - "|({}){}|", - found_args - .iter() - .map(|arg| match arg { - ArgKind::Arg(name, _) => name.to_owned(), - _ => "_".to_owned(), - }) - .collect::>() - .join(", "), - // add type annotations if available - if found_args.iter().any(|arg| match arg { - ArgKind::Arg(_, ty) => ty != "_", - _ => false, - }) { - format!( - ": ({})", - fields - .iter() - .map(|(_, ty)| ty.to_owned()) - .collect::>() - .join(", ") - ) - } else { - String::new() - }, - ); - err.span_suggestion_verbose( - found_span, - "change the closure to accept a tuple instead of individual arguments", - sugg, - Applicability::MachineApplicable, - ); - } + if let &[ArgKind::Tuple(_, ref fields)] = &expected_args[..] + && fields.len() == found_args.len() + && is_closure + { + let sugg = format!( + "|({}){}|", + found_args + .iter() + .map(|arg| match arg { + ArgKind::Arg(name, _) => name.to_owned(), + _ => "_".to_owned(), + }) + .collect::>() + .join(", "), + // add type annotations if available + if found_args.iter().any(|arg| match arg { + ArgKind::Arg(_, ty) => ty != "_", + _ => false, + }) { + format!( + ": ({})", + fields + .iter() + .map(|(_, ty)| ty.to_owned()) + .collect::>() + .join(", ") + ) + } else { + String::new() + }, + ); + err.span_suggestion_verbose( + found_span, + "change the closure to accept a tuple instead of individual arguments", + sugg, + Applicability::MachineApplicable, + ); } } @@ -2231,16 +2232,13 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { if obligated_types.iter().any(|ot| ot == &self_ty) { return true; } - if let ty::Adt(def, substs) = self_ty.kind() { - if let [arg] = &substs[..] { - if let ty::subst::GenericArgKind::Type(ty) = arg.unpack() { - if let ty::Adt(inner_def, _) = ty.kind() { - if inner_def == def { - return true; - } - } - } - } + if let ty::Adt(def, substs) = self_ty.kind() + && let [arg] = &substs[..] + && let ty::subst::GenericArgKind::Type(ty) = arg.unpack() + && let ty::Adt(inner_def, _) = ty.kind() + && inner_def == def + { + return true; } } false 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 45bfb2b1e9413..7af2ba8b30f87 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -891,23 +891,20 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { } if let Some(typeck_results) = self.in_progress_typeck_results.map(|t| t.borrow()) + && let ty = typeck_results.expr_ty_adjusted(base) + && let ty::FnDef(def_id, _substs) = ty.kind() + && let Some(hir::Node::Item(hir::Item { span, ident, .. })) = + hir.get_if_local(*def_id) { - let ty = typeck_results.expr_ty_adjusted(base); - if let ty::FnDef(def_id, _substs) = ty.kind() { - if let Some(hir::Node::Item(hir::Item { span, ident, .. })) = - hir.get_if_local(*def_id) - { - err.span_suggestion_verbose( - span.shrink_to_lo(), - &format!( - "alternatively, consider making `fn {}` asynchronous", - ident - ), - "async ".to_string(), - Applicability::MaybeIncorrect, - ); - } - } + err.span_suggestion_verbose( + span.shrink_to_lo(), + &format!( + "alternatively, consider making `fn {}` asynchronous", + ident + ), + "async ".to_string(), + Applicability::MaybeIncorrect, + ); } } } @@ -1000,34 +997,24 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { span: Span, trait_pred: ty::PolyTraitPredicate<'tcx>, ) { - let is_empty_tuple = - |ty: ty::Binder<'tcx, Ty<'_>>| *ty.skip_binder().kind() == ty::Tuple(ty::List::empty()); - let hir = self.tcx.hir(); let parent_node = hir.get_parent_node(obligation.cause.body_id); let node = hir.find(parent_node); - if let Some(hir::Node::Item(hir::Item { - kind: hir::ItemKind::Fn(sig, _, body_id), .. - })) = node + if let Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, _, body_id), .. })) = node + && let body = hir.body(*body_id) + && let hir::ExprKind::Block(blk, _) = &body.value.kind + && sig.decl.output.span().overlaps(span) + && blk.expr.is_none() + && *trait_pred.self_ty().skip_binder().kind() == ty::Tuple(ty::List::empty()) + // FIXME(estebank): When encountering a method with a trait + // bound not satisfied in the return type with a body that has + // no return, suggest removal of semicolon on last statement. + // Once that is added, close #54771. + && let Some(stmt) = blk.stmts.last() + && let hir::StmtKind::Semi(_) = stmt.kind { - let body = hir.body(*body_id); - if let hir::ExprKind::Block(blk, _) = &body.value.kind { - if sig.decl.output.span().overlaps(span) - && blk.expr.is_none() - && is_empty_tuple(trait_pred.self_ty()) - { - // FIXME(estebank): When encountering a method with a trait - // bound not satisfied in the return type with a body that has - // no return, suggest removal of semicolon on last statement. - // Once that is added, close #54771. - if let Some(ref stmt) = blk.stmts.last() { - if let hir::StmtKind::Semi(_) = stmt.kind { - let sp = self.tcx.sess.source_map().end_point(stmt.span); - err.span_label(sp, "consider removing this semicolon"); - } - } - } - } + let sp = self.tcx.sess.source_map().end_point(stmt.span); + err.span_label(sp, "consider removing this semicolon"); } } @@ -2481,17 +2468,15 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { debug!("suggest_await_before_try: try_trait_obligation {:?}", try_obligation); if self.predicate_may_hold(&try_obligation) && impls_future.must_apply_modulo_regions() + && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) + && snippet.ends_with('?') { - if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { - if snippet.ends_with('?') { - err.span_suggestion_verbose( - span.with_hi(span.hi() - BytePos(1)).shrink_to_hi(), - "consider `await`ing on the `Future`", - ".await".to_string(), - Applicability::MaybeIncorrect, - ); - } - } + err.span_suggestion_verbose( + span.with_hi(span.hi() - BytePos(1)).shrink_to_hi(), + "consider `await`ing on the `Future`", + ".await".to_string(), + Applicability::MaybeIncorrect, + ); } } } diff --git a/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs index b05dbbe898a41..7fbdd3689a7eb 100644 --- a/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs @@ -91,10 +91,8 @@ impl<'tcx> OnUnimplementedDirective { ) })?; attr::eval_condition(cond, &tcx.sess.parse_sess, Some(tcx.features()), &mut |item| { - if let Some(symbol) = item.value_str() { - if parse_value(symbol).is_err() { - errored = true; - } + if let Some(symbol) = item.value_str() && parse_value(symbol).is_err() { + errored = true; } true }); @@ -232,24 +230,22 @@ impl<'tcx> OnUnimplementedDirective { options.iter().filter_map(|(k, v)| v.as_ref().map(|v| (*k, v.to_owned()))).collect(); for command in self.subcommands.iter().chain(Some(self)).rev() { - if let Some(ref condition) = command.condition { - if !attr::eval_condition( - condition, - &tcx.sess.parse_sess, - Some(tcx.features()), - &mut |c| { - c.ident().map_or(false, |ident| { - let value = c.value_str().map(|s| { - OnUnimplementedFormatString(s).format(tcx, trait_ref, &options_map) - }); + if let Some(ref condition) = command.condition && !attr::eval_condition( + condition, + &tcx.sess.parse_sess, + Some(tcx.features()), + &mut |c| { + c.ident().map_or(false, |ident| { + let value = c.value_str().map(|s| { + OnUnimplementedFormatString(s).format(tcx, trait_ref, &options_map) + }); - options.contains(&(ident.name, value)) - }) - }, - ) { - debug!("evaluate: skipping {:?} due to condition", command); - continue; - } + options.contains(&(ident.name, value)) + }) + }, + ) { + debug!("evaluate: skipping {:?} due to condition", command); + continue; } debug!("evaluate: {:?} succeeded", command); if let Some(ref message_) = command.message { diff --git a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs index 066f3ffada57a..435d709d37e60 100644 --- a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs +++ b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs @@ -43,21 +43,19 @@ impl<'cx, 'tcx> AtExt<'tcx> for At<'cx, 'tcx> { let c_ty = self.infcx.canonicalize_query(self.param_env.and(ty), &mut orig_values); let span = self.cause.span; debug!("c_ty = {:?}", c_ty); - if let Ok(result) = tcx.dropck_outlives(c_ty) { - if result.is_proven() { - if let Ok(InferOk { value, obligations }) = - self.infcx.instantiate_query_response_and_region_obligations( - self.cause, - self.param_env, - &orig_values, - result, - ) - { - let ty = self.infcx.resolve_vars_if_possible(ty); - let kinds = value.into_kinds_reporting_overflows(tcx, span, ty); - return InferOk { value: kinds, obligations }; - } - } + if let Ok(result) = tcx.dropck_outlives(c_ty) + && result.is_proven() + && let Ok(InferOk { value, obligations }) = + self.infcx.instantiate_query_response_and_region_obligations( + self.cause, + self.param_env, + &orig_values, + result, + ) + { + let ty = self.infcx.resolve_vars_if_possible(ty); + let kinds = value.into_kinds_reporting_overflows(tcx, span, ty); + return InferOk { value: kinds, obligations }; } // Errors and ambiuity in dropck occur in two cases: diff --git a/compiler/rustc_trait_selection/src/traits/relationships.rs b/compiler/rustc_trait_selection/src/traits/relationships.rs index aea44841b8f12..b13646ba1a0c2 100644 --- a/compiler/rustc_trait_selection/src/traits/relationships.rs +++ b/compiler/rustc_trait_selection/src/traits/relationships.rs @@ -12,50 +12,38 @@ pub(crate) fn update<'tcx, T>( T: TraitEngine<'tcx>, { // (*) binder skipped - if let ty::PredicateKind::Trait(predicate) = obligation.predicate.kind().skip_binder() { - if let Some(ty) = - infcx.shallow_resolve(predicate.self_ty()).ty_vid().map(|t| infcx.root_var(t)) - { - if infcx - .tcx - .lang_items() - .sized_trait() - .map_or(false, |st| st != predicate.trait_ref.def_id) - { - let new_self_ty = infcx.tcx.types.unit; + if let ty::PredicateKind::Trait(tpred) = obligation.predicate.kind().skip_binder() + && let Some(ty) = infcx.shallow_resolve(tpred.self_ty()).ty_vid().map(|t| infcx.root_var(t)) + && infcx.tcx.lang_items().sized_trait().map_or(false, |st| st != tpred.trait_ref.def_id) + { + let new_self_ty = infcx.tcx.types.unit; - let trait_ref = ty::TraitRef { - substs: infcx - .tcx - .mk_substs_trait(new_self_ty, &predicate.trait_ref.substs[1..]), - ..predicate.trait_ref - }; + let trait_ref = ty::TraitRef { + substs: infcx.tcx.mk_substs_trait(new_self_ty, &tpred.trait_ref.substs[1..]), + ..tpred.trait_ref + }; - // Then contstruct a new obligation with Self = () added - // to the ParamEnv, and see if it holds. - let o = rustc_infer::traits::Obligation::new( - ObligationCause::dummy(), - obligation.param_env, - obligation - .predicate - .kind() - .map_bound(|_| { - // (*) binder moved here - ty::PredicateKind::Trait(ty::TraitPredicate { - trait_ref, - constness: predicate.constness, - polarity: predicate.polarity, - }) - }) - .to_predicate(infcx.tcx), - ); - // Don't report overflow errors. Otherwise equivalent to may_hold. - if let Ok(result) = infcx.probe(|_| infcx.evaluate_obligation(&o)) { - if result.may_apply() { - engine.relationships().entry(ty).or_default().self_in_trait = true; - } - } - } + // Then contstruct a new obligation with Self = () added + // to the ParamEnv, and see if it holds. + let o = rustc_infer::traits::Obligation::new( + ObligationCause::dummy(), + obligation.param_env, + obligation + .predicate + .kind() + .map_bound(|_| { + // (*) binder moved here + ty::PredicateKind::Trait(ty::TraitPredicate { + trait_ref, + constness: tpred.constness, + polarity: tpred.polarity, + }) + }) + .to_predicate(infcx.tcx), + ); + // Don't report overflow errors. Otherwise equivalent to may_hold. + if let Ok(result) = infcx.probe(|_| infcx.evaluate_obligation(&o)) && result.may_apply() { + engine.relationships().entry(ty).or_default().self_in_trait = true; } } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 8bcb1ccb5846d..f3c7642f7a318 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -579,24 +579,22 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { previous_stack, subobligations, ); - if let Ok(res) = res { - if res == EvaluatedToOk || res == EvaluatedToOkModuloRegions { - if let Some(key) = - ProjectionCacheKey::from_poly_projection_predicate( - self, data, - ) - { - // If the result is something that we can cache, then mark this - // entry as 'complete'. This will allow us to skip evaluating the - // suboligations at all the next time we evaluate the projection - // predicate. - self.infcx - .inner - .borrow_mut() - .projection_cache() - .complete(key, res); - } - } + if let Ok(eval_rslt) = res + && (eval_rslt == EvaluatedToOk || eval_rslt == EvaluatedToOkModuloRegions) + && let Some(key) = + ProjectionCacheKey::from_poly_projection_predicate( + self, data, + ) + { + // If the result is something that we can cache, then mark this + // entry as 'complete'. This will allow us to skip evaluating the + // suboligations at all the next time we evaluate the projection + // predicate. + self.infcx + .inner + .borrow_mut() + .projection_cache() + .complete(key, eval_rslt); } res } diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 7da5c50d2307d..943f36efc153f 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -224,36 +224,30 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>( // projection coming from another associated type. See // `src/test/ui/associated-types/point-at-type-on-obligation-failure.rs` and // `traits-assoc-type-in-supertrait-bad.rs`. - if let Some(ty::Projection(projection_ty)) = proj.term.ty().map(|ty| ty.kind()) { - if let Some(&impl_item_id) = + if let Some(ty::Projection(projection_ty)) = proj.term.ty().map(|ty| ty.kind()) + && let Some(&impl_item_id) = tcx.impl_item_implementor_ids(impl_def_id).get(&projection_ty.item_def_id) - { - if let Some(impl_item_span) = items - .iter() - .find(|item| item.id.def_id.to_def_id() == impl_item_id) - .map(fix_span) - { - cause.span = impl_item_span; - } - } + && let Some(impl_item_span) = items + .iter() + .find(|item| item.id.def_id.to_def_id() == impl_item_id) + .map(fix_span) + { + cause.span = impl_item_span; } } ty::PredicateKind::Trait(pred) => { // An associated item obligation born out of the `trait` failed to be met. An example // can be seen in `ui/associated-types/point-at-type-on-obligation-failure-2.rs`. debug!("extended_cause_with_original_assoc_item_obligation trait proj {:?}", pred); - if let ty::Projection(ty::ProjectionTy { item_def_id, .. }) = *pred.self_ty().kind() { - if let Some(&impl_item_id) = + if let ty::Projection(ty::ProjectionTy { item_def_id, .. }) = *pred.self_ty().kind() + && let Some(&impl_item_id) = tcx.impl_item_implementor_ids(impl_def_id).get(&item_def_id) - { - if let Some(impl_item_span) = items - .iter() - .find(|item| item.id.def_id.to_def_id() == impl_item_id) - .map(fix_span) - { - cause.span = impl_item_span; - } - } + && let Some(impl_item_span) = items + .iter() + .find(|item| item.id.def_id.to_def_id() == impl_item_id) + .map(fix_span) + { + cause.span = impl_item_span; } } _ => {}