From 99fa572ab170c1b26e17e2b52c6a417215aca512 Mon Sep 17 00:00:00 2001 From: b-naber Date: Sun, 22 May 2022 17:00:23 +0200 Subject: [PATCH 1/6] add def_id and substs to ConstraintCategory::CallArgument --- .../rustc_borrowck/src/constraints/mod.rs | 2 +- .../src/diagnostics/conflict_errors.rs | 14 +++--- .../src/diagnostics/explain_borrow.rs | 14 +++--- .../rustc_borrowck/src/region_infer/mod.rs | 8 +-- .../src/type_check/canonical.rs | 10 ++-- .../src/type_check/constraint_conversion.rs | 4 +- compiler/rustc_borrowck/src/type_check/mod.rs | 49 ++++++++++++++++--- .../src/type_check/relate_tys.rs | 6 +-- compiler/rustc_middle/src/mir/query.rs | 11 ++--- compiler/rustc_middle/src/ty/impls_ty.rs | 4 +- 10 files changed, 77 insertions(+), 45 deletions(-) diff --git a/compiler/rustc_borrowck/src/constraints/mod.rs b/compiler/rustc_borrowck/src/constraints/mod.rs index 6d5466c0c41e3..a504d0c91222e 100644 --- a/compiler/rustc_borrowck/src/constraints/mod.rs +++ b/compiler/rustc_borrowck/src/constraints/mod.rs @@ -95,7 +95,7 @@ pub struct OutlivesConstraint<'tcx> { pub span: Span, /// What caused this constraint? - pub category: ConstraintCategory, + pub category: ConstraintCategory<'tcx>, /// Variance diagnostic information pub variance_info: VarianceDiagInfo<'tcx>, diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index da5f56704d41f..191574d7a8fb9 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -788,7 +788,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { err: &mut Diagnostic, location: Location, issued_borrow: &BorrowData<'tcx>, - explanation: BorrowExplanation, + explanation: BorrowExplanation<'tcx>, ) { let used_in_call = matches!( explanation, @@ -1088,7 +1088,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { BorrowExplanation::MustBeValidFor { category: category @ (ConstraintCategory::Return(_) - | ConstraintCategory::CallArgument + | ConstraintCategory::CallArgument(_) | ConstraintCategory::OpaqueType), from_closure: false, ref region_name, @@ -1147,7 +1147,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { borrow: &BorrowData<'tcx>, drop_span: Span, borrow_spans: UseSpans<'tcx>, - explanation: BorrowExplanation, + explanation: BorrowExplanation<'tcx>, ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { debug!( "report_local_value_does_not_live_long_enough(\ @@ -1352,7 +1352,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { drop_span: Span, borrow_spans: UseSpans<'tcx>, proper_span: Span, - explanation: BorrowExplanation, + explanation: BorrowExplanation<'tcx>, ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { debug!( "report_temporary_value_does_not_live_long_enough(\ @@ -1410,7 +1410,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { borrow: &BorrowData<'tcx>, borrow_span: Span, return_span: Span, - category: ConstraintCategory, + category: ConstraintCategory<'tcx>, opt_place_desc: Option<&String>, ) -> Option> { let return_kind = match category { @@ -1508,7 +1508,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { use_span: UseSpans<'tcx>, var_span: Span, fr_name: &RegionName, - category: ConstraintCategory, + category: ConstraintCategory<'tcx>, constraint_span: Span, captured_var: &str, ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { @@ -1559,7 +1559,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let msg = format!("{} is returned here", kind); err.span_note(constraint_span, &msg); } - ConstraintCategory::CallArgument => { + ConstraintCategory::CallArgument(_) => { fr_name.highlight_region_name(&mut err); if matches!(use_span.generator_kind(), Some(GeneratorKind::Async(_))) { err.note( diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index 0b6be453b9231..5d9e5907dffb0 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -24,7 +24,7 @@ use crate::{ use super::{find_use, RegionName, UseSpans}; #[derive(Debug)] -pub(crate) enum BorrowExplanation { +pub(crate) enum BorrowExplanation<'tcx> { UsedLater(LaterUseKind, Span, Option), UsedLaterInLoop(LaterUseKind, Span, Option), UsedLaterWhenDropped { @@ -33,7 +33,7 @@ pub(crate) enum BorrowExplanation { should_note_order: bool, }, MustBeValidFor { - category: ConstraintCategory, + category: ConstraintCategory<'tcx>, from_closure: bool, span: Span, region_name: RegionName, @@ -51,11 +51,11 @@ pub(crate) enum LaterUseKind { Other, } -impl BorrowExplanation { +impl<'tcx> BorrowExplanation<'tcx> { pub(crate) fn is_explained(&self) -> bool { !matches!(self, BorrowExplanation::Unexplained) } - pub(crate) fn add_explanation_to_diagnostic<'tcx>( + pub(crate) fn add_explanation_to_diagnostic( &self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>, @@ -276,7 +276,7 @@ impl BorrowExplanation { pub(crate) fn add_lifetime_bound_suggestion_to_diagnostic( &self, err: &mut Diagnostic, - category: &ConstraintCategory, + category: &ConstraintCategory<'tcx>, span: Span, region_name: &RegionName, ) { @@ -305,7 +305,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { &self, borrow_region: RegionVid, outlived_region: RegionVid, - ) -> (ConstraintCategory, bool, Span, Option) { + ) -> (ConstraintCategory<'tcx>, bool, Span, Option) { let BlameConstraint { category, from_closure, cause, variance_info: _ } = self.regioncx.best_blame_constraint( &self.body, @@ -337,7 +337,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { location: Location, borrow: &BorrowData<'tcx>, kind_place: Option<(WriteKind, Place<'tcx>)>, - ) -> BorrowExplanation { + ) -> BorrowExplanation<'tcx> { debug!( "explain_why_borrow_contains_point(location={:?}, borrow={:?}, kind_place={:?})", location, borrow, kind_place diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index dc6337c54edd9..2c460bcb72d8b 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -87,7 +87,7 @@ pub struct RegionInferenceContext<'tcx> { /// Map closure bounds to a `Span` that should be used for error reporting. closure_bounds_mapping: - FxHashMap>, + FxHashMap, Span)>>, /// Map universe indexes to information on why we created it. universe_causes: FxHashMap>, @@ -259,7 +259,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { member_constraints_in: MemberConstraintSet<'tcx, RegionVid>, closure_bounds_mapping: FxHashMap< Location, - FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>, + FxHashMap<(RegionVid, RegionVid), (ConstraintCategory<'tcx>, Span)>, >, universe_causes: FxHashMap>, type_tests: Vec>, @@ -1772,7 +1772,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { fr1: RegionVid, fr1_origin: NllRegionVariableOrigin, fr2: RegionVid, - ) -> (ConstraintCategory, ObligationCause<'tcx>) { + ) -> (ConstraintCategory<'tcx>, ObligationCause<'tcx>) { let BlameConstraint { category, cause, .. } = self.best_blame_constraint(body, fr1, fr1_origin, |r| { self.provides_universal_region(r, fr1, fr2) @@ -2270,7 +2270,7 @@ impl<'tcx> ClosureRegionRequirementsExt<'tcx> for ClosureRegionRequirements<'tcx #[derive(Clone, Debug)] pub struct BlameConstraint<'tcx> { - pub category: ConstraintCategory, + pub category: ConstraintCategory<'tcx>, pub from_closure: bool, pub cause: ObligationCause<'tcx>, pub variance_info: ty::VarianceDiagInfo<'tcx>, diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs index 3856b7f4a4b82..55c0bf05b4873 100644 --- a/compiler/rustc_borrowck/src/type_check/canonical.rs +++ b/compiler/rustc_borrowck/src/type_check/canonical.rs @@ -28,7 +28,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { pub(super) fn fully_perform_op( &mut self, locations: Locations, - category: ConstraintCategory, + category: ConstraintCategory<'tcx>, op: Op, ) -> Fallible where @@ -83,11 +83,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { instantiated } + #[instrument(skip(self), level = "debug")] pub(super) fn prove_trait_ref( &mut self, trait_ref: ty::TraitRef<'tcx>, locations: Locations, - category: ConstraintCategory, + category: ConstraintCategory<'tcx>, ) { self.prove_predicates( Some(ty::Binder::dummy(ty::PredicateKind::Trait(ty::TraitPredicate { @@ -113,6 +114,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { .into_iter() .zip(instantiated_predicates.spans.into_iter()) { + debug!(?predicate); let predicate = self.normalize(predicate, locations); self.prove_predicate(predicate, locations, ConstraintCategory::Predicate(span)); } @@ -122,7 +124,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { &mut self, predicates: impl IntoIterator>, locations: Locations, - category: ConstraintCategory, + category: ConstraintCategory<'tcx>, ) { for predicate in predicates { let predicate = predicate.to_predicate(self.tcx()); @@ -137,7 +139,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { &mut self, predicate: ty::Predicate<'tcx>, locations: Locations, - category: ConstraintCategory, + category: ConstraintCategory<'tcx>, ) { let param_env = self.param_env; self.fully_perform_op( diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs index f11a94d7ddd23..3c9e3870aeac4 100644 --- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs +++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs @@ -27,7 +27,7 @@ pub(crate) struct ConstraintConversion<'a, 'tcx> { param_env: ty::ParamEnv<'tcx>, locations: Locations, span: Span, - category: ConstraintCategory, + category: ConstraintCategory<'tcx>, constraints: &'a mut MirTypeckRegionConstraints<'tcx>, } @@ -40,7 +40,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { param_env: ty::ParamEnv<'tcx>, locations: Locations, span: Span, - category: ConstraintCategory, + category: ConstraintCategory<'tcx>, constraints: &'a mut MirTypeckRegionConstraints<'tcx>, ) -> Self { Self { diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 34bc87b20c79a..bf52b1be6782e 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -162,6 +162,8 @@ pub(crate) fn type_check<'mir, 'tcx>( &mut constraints, ); + debug!(?normalized_inputs_and_output); + for u in ty::UniverseIndex::ROOT..infcx.universe() { let info = UniverseInfo::other(); constraints.universe_causes.insert(u, info); @@ -185,6 +187,7 @@ pub(crate) fn type_check<'mir, 'tcx>( implicit_region_bound, &mut borrowck_context, |mut cx| { + debug!("inside extra closure of type_check_internal"); cx.equate_inputs_and_outputs(&body, universal_regions, &normalized_inputs_and_output); liveness::generate( &mut cx, @@ -257,6 +260,7 @@ fn type_check_internal<'a, 'tcx, R>( borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>, extra: impl FnOnce(TypeChecker<'a, 'tcx>) -> R, ) -> R { + debug!("body: {:#?}", body); let mut checker = TypeChecker::new( infcx, body, @@ -934,8 +938,8 @@ pub(crate) struct MirTypeckRegionConstraints<'tcx> { pub(crate) member_constraints: MemberConstraintSet<'tcx, RegionVid>, - pub(crate) closure_bounds_mapping: - FxHashMap>, + crate closure_bounds_mapping: + FxHashMap, Span)>>, pub(crate) universe_causes: FxHashMap>, @@ -1125,7 +1129,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { fn push_region_constraints( &mut self, locations: Locations, - category: ConstraintCategory, + category: ConstraintCategory<'tcx>, data: &QueryRegionConstraints<'tcx>, ) { debug!("constraints generated: {:#?}", data); @@ -1150,7 +1154,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { sub: Ty<'tcx>, sup: Ty<'tcx>, locations: Locations, - category: ConstraintCategory, + category: ConstraintCategory<'tcx>, ) -> Fallible<()> { // Use this order of parameters because the sup type is usually the // "expected" type in diagnostics. @@ -1163,7 +1167,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { expected: Ty<'tcx>, found: Ty<'tcx>, locations: Locations, - category: ConstraintCategory, + category: ConstraintCategory<'tcx>, ) -> Fallible<()> { self.relate_types(expected, ty::Variance::Invariant, found, locations, category) } @@ -1175,7 +1179,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { v: ty::Variance, user_ty: &UserTypeProjection, locations: Locations, - category: ConstraintCategory, + category: ConstraintCategory<'tcx>, ) -> Fallible<()> { let annotated_type = self.user_type_annotations[user_ty.base].inferred_ty; let mut curr_projected_ty = PlaceTy::from_ty(annotated_type); @@ -1212,6 +1216,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { #[instrument(skip(self, body, location), level = "debug")] fn check_stmt(&mut self, body: &Body<'tcx>, stmt: &Statement<'tcx>, location: Location) { let tcx = self.tcx(); + debug!("stmt kind: {:?}", stmt.kind); match stmt.kind { StatementKind::Assign(box (ref place, ref rv)) => { // Assignments to temporaries are not "interesting"; @@ -1251,9 +1256,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ); let place_ty = place.ty(body, tcx).ty; + debug!(?place_ty); let place_ty = self.normalize(place_ty, location); + debug!("place_ty normalized: {:?}", place_ty); let rv_ty = rv.ty(body, tcx); + debug!(?rv_ty); let rv_ty = self.normalize(rv_ty, location); + debug!("normalized rv_ty: {:?}", rv_ty); if let Err(terr) = self.sub_types(rv_ty, place_ty, location.to_locations(), category) { @@ -1347,6 +1356,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { term_location: Location, ) { let tcx = self.tcx(); + debug!("terminator kind: {:?}", term.kind); match term.kind { TerminatorKind::Goto { .. } | TerminatorKind::Resume @@ -1404,7 +1414,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // FIXME: check the values } TerminatorKind::Call { - ref func, ref args, destination, target, from_hir_call, .. + ref func, + ref args, + ref destination, + from_hir_call, + fn_span, + .. } => { self.check_operand(func, term_location); for arg in args { @@ -1413,6 +1428,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let func_ty = func.ty(body, tcx); debug!("check_terminator: call, func_ty={:?}", func_ty); + debug!("func_ty.kind: {:?}", func_ty.kind()); + debug!(?fn_span); let sig = match func_ty.kind() { ty::FnDef(..) | ty::FnPtr(_) => func_ty.fn_sig(tcx), _ => { @@ -1425,6 +1442,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { LateBoundRegionConversionTime::FnCall, sig, ); + debug!(?sig); let sig = self.normalize(sig, term_location); self.check_call_dest(body, term, &sig, destination, target, term_location); @@ -1585,11 +1603,25 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { if args.len() < sig.inputs().len() || (args.len() > sig.inputs().len() && !sig.c_variadic) { span_mirbug!(self, term, "call to {:?} with wrong # of args", sig); } + + let call_arg = if let TerminatorKind::Call { func, .. } = &term.kind { + let func_ty = func.ty(body, self.infcx.tcx); + if let ty::FnDef(fn_did, substs) = func_ty.kind() { + Some((*fn_did, *substs)) + } else { + None + } + } else { + None + }; + debug!(?call_arg); + for (n, (fn_arg, op_arg)) in iter::zip(sig.inputs(), args).enumerate() { let op_arg_ty = op_arg.ty(body, self.tcx()); + let op_arg_ty = self.normalize(op_arg_ty, term_location); let category = if from_hir_call { - ConstraintCategory::CallArgument + ConstraintCategory::CallArgument(call_arg) } else { ConstraintCategory::Boring }; @@ -1841,6 +1873,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } } + #[instrument(skip(self, body), level = "debug")] fn check_rvalue(&mut self, body: &Body<'tcx>, rvalue: &Rvalue<'tcx>, location: Location) { let tcx = self.tcx(); diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index f98d2c3128c52..c45850c6d840f 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -28,7 +28,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { v: ty::Variance, b: Ty<'tcx>, locations: Locations, - category: ConstraintCategory, + category: ConstraintCategory<'tcx>, ) -> Fallible<()> { TypeRelating::new( self.infcx, @@ -47,7 +47,7 @@ struct NllTypeRelatingDelegate<'me, 'bccx, 'tcx> { locations: Locations, /// What category do we assign the resulting `'a: 'b` relationships? - category: ConstraintCategory, + category: ConstraintCategory<'tcx>, /// Information so that error reporting knows what types we are relating /// when reporting a bound region error. @@ -58,7 +58,7 @@ impl<'me, 'bccx, 'tcx> NllTypeRelatingDelegate<'me, 'bccx, 'tcx> { fn new( type_checker: &'me mut TypeChecker<'bccx, 'tcx>, locations: Locations, - category: ConstraintCategory, + category: ConstraintCategory<'tcx>, universe_info: UniverseInfo<'tcx>, ) -> Self { Self { type_checker, locations, category, universe_info } diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index 7f7b8bdfc1461..4f71e3a8234fa 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -1,7 +1,7 @@ //! Values computed by queries that use MIR. use crate::mir::{self, Body, Promoted}; -use crate::ty::{self, OpaqueHiddenType, Ty, TyCtxt}; +use crate::ty::{self, subst::SubstsRef, OpaqueHiddenType, Ty, TyCtxt}; use rustc_data_structures::stable_map::FxHashMap; use rustc_data_structures::vec_map::VecMap; use rustc_errors::ErrorGuaranteed; @@ -338,12 +338,9 @@ pub struct ClosureOutlivesRequirement<'tcx> { pub blame_span: Span, // ... due to this reason. - pub category: ConstraintCategory, + pub category: ConstraintCategory<'tcx>, } -// Make sure this enum doesn't unintentionally grow -rustc_data_structures::static_assert_size!(ConstraintCategory, 12); - /// Outlives-constraints can be categorized to determine whether and why they /// are interesting (for error reporting). Order of variants indicates sort /// order of the category, thereby influencing diagnostic output. @@ -351,7 +348,7 @@ rustc_data_structures::static_assert_size!(ConstraintCategory, 12); /// See also `rustc_const_eval::borrow_check::constraints`. #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] #[derive(TyEncodable, TyDecodable, HashStable)] -pub enum ConstraintCategory { +pub enum ConstraintCategory<'tcx> { Return(ReturnConstraint), Yield, UseAsConst, @@ -363,7 +360,7 @@ pub enum ConstraintCategory { /// /// We try to get the category that the closure used when reporting this. ClosureBounds, - CallArgument, + CallArgument(Option<(DefId, SubstsRef<'tcx>)>), CopyBound, SizedBound, Assignment, diff --git a/compiler/rustc_middle/src/ty/impls_ty.rs b/compiler/rustc_middle/src/ty/impls_ty.rs index 65c9b1aed050e..d6b5e9ddfbd6f 100644 --- a/compiler/rustc_middle/src/ty/impls_ty.rs +++ b/compiler/rustc_middle/src/ty/impls_ty.rs @@ -135,8 +135,8 @@ impl<'a> HashStable> for ty::RegionKind { ty::RePlaceholder(p) => { p.hash_stable(hcx, hasher); } - ty::ReVar(..) => { - bug!("StableHasher: unexpected region {:?}", *self) + ty::ReVar(reg_vid) => { + reg_vid.hash_stable(hcx, hasher); } } } From c1072d2a9a514f11166eaf334140d33d257a120e Mon Sep 17 00:00:00 2001 From: b-naber Date: Sun, 22 May 2022 17:02:27 +0200 Subject: [PATCH 2/6] make TraitObject visitors public --- .../src/infer/error_reporting/nice_region_error/mod.rs | 2 +- .../error_reporting/nice_region_error/static_impl_trait.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs index 9948d15c43115..53d9acf7d2908 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs @@ -16,7 +16,7 @@ mod util; pub use different_lifetimes::suggest_adding_lifetime_params; pub use find_anon_type::find_anon_type; -pub use static_impl_trait::suggest_new_region_bound; +pub use static_impl_trait::{suggest_new_region_bound, HirTraitObjectVisitor, TraitObjectVisitor}; pub use util::find_param_with_region; impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs index a4c46d5cf0ba2..1081f888f7ff3 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -546,7 +546,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { } /// Collect all the trait objects in a type that could have received an implicit `'static` lifetime. -pub(super) struct TraitObjectVisitor(pub(super) FxHashSet); +pub struct TraitObjectVisitor(pub FxHashSet); impl<'tcx> TypeVisitor<'tcx> for TraitObjectVisitor { fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { @@ -563,7 +563,7 @@ impl<'tcx> TypeVisitor<'tcx> for TraitObjectVisitor { } /// Collect all `hir::Ty<'_>` `Span`s for trait objects with an implicit lifetime. -pub(super) struct HirTraitObjectVisitor<'a>(pub(super) &'a mut Vec, pub(super) DefId); +pub struct HirTraitObjectVisitor<'a>(pub &'a mut Vec, pub DefId); impl<'a, 'tcx> Visitor<'tcx> for HirTraitObjectVisitor<'a> { fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx>) { From 5f65331b3eff0a66a695127ec890638bb67e039f Mon Sep 17 00:00:00 2001 From: b-naber Date: Sun, 22 May 2022 17:04:49 +0200 Subject: [PATCH 3/6] suggest constraining dyn trait in impl in NLL --- .../src/diagnostics/outlives_suggestion.rs | 2 +- .../src/diagnostics/region_errors.rs | 221 +++++++++++++++--- compiler/rustc_borrowck/src/type_check/mod.rs | 2 +- .../error_reporting/nice_region_error/util.rs | 11 + 4 files changed, 208 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs index 1688d1259fa86..9d81330745fe2 100644 --- a/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs +++ b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs @@ -161,7 +161,7 @@ impl OutlivesSuggestionBuilder { pub(crate) fn intermediate_suggestion( &mut self, mbcx: &MirBorrowckCtxt<'_, '_>, - errci: &ErrorConstraintInfo, + errci: &ErrorConstraintInfo<'_>, diag: &mut Diagnostic, ) { // Emit an intermediate note. diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index f2b5c83c5c1d0..a637f0613d172 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -1,10 +1,14 @@ //! Error reporting machinery for lifetime errors. -use rustc_errors::{Diagnostic, DiagnosticBuilder, ErrorGuaranteed}; +use rustc_data_structures::stable_set::FxHashSet; +use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan}; +use rustc_hir::def_id::DefId; +use rustc_hir::intravisit::Visitor; +use rustc_hir::{self as hir, Item, ItemKind, Node}; use rustc_infer::infer::{ error_reporting::nice_region_error::{ self, find_anon_type, find_param_with_region, suggest_adding_lifetime_params, - NiceRegionError, + HirTraitObjectVisitor, NiceRegionError, TraitObjectVisitor, }, error_reporting::unexpected_hidden_region_diagnostic, NllRegionVariableOrigin, RelateParamBound, @@ -12,8 +16,11 @@ use rustc_infer::infer::{ use rustc_middle::hir::place::PlaceBase; use rustc_middle::mir::{ConstraintCategory, ReturnConstraint}; use rustc_middle::ty::subst::InternalSubsts; +use rustc_middle::ty::Region; +use rustc_middle::ty::TypeVisitor; use rustc_middle::ty::{self, RegionVid, Ty}; use rustc_span::symbol::sym; +use rustc_span::symbol::Ident; use rustc_span::Span; use crate::borrowck_errors; @@ -27,7 +34,7 @@ use crate::{ MirBorrowckCtxt, }; -impl ConstraintDescription for ConstraintCategory { +impl<'tcx> ConstraintDescription for ConstraintCategory<'tcx> { fn description(&self) -> &'static str { // Must end with a space. Allows for empty names to be provided. match self { @@ -37,7 +44,7 @@ impl ConstraintDescription for ConstraintCategory { ConstraintCategory::UseAsConst => "using this value as a constant ", ConstraintCategory::UseAsStatic => "using this value as a static ", ConstraintCategory::Cast => "cast ", - ConstraintCategory::CallArgument => "argument ", + ConstraintCategory::CallArgument(_) => "argument ", ConstraintCategory::TypeAnnotation => "type annotation ", ConstraintCategory::ClosureBounds => "closure body ", ConstraintCategory::SizedBound => "proving this value is `Sized` ", @@ -101,7 +108,7 @@ pub(crate) enum RegionErrorKind<'tcx> { /// Information about the various region constraints involved in a borrow checker error. #[derive(Clone, Debug)] -pub struct ErrorConstraintInfo { +pub struct ErrorConstraintInfo<'tcx> { // fr: outlived_fr pub(super) fr: RegionVid, pub(super) fr_is_local: bool, @@ -109,7 +116,7 @@ pub struct ErrorConstraintInfo { pub(super) outlived_fr_is_local: bool, // Category and span for best blame constraint - pub(super) category: ConstraintCategory, + pub(super) category: ConstraintCategory<'tcx>, pub(super) span: Span, } @@ -256,6 +263,70 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { outlives_suggestion.add_suggestion(self); } + fn get_impl_ident_and_self_ty_from_trait( + &self, + def_id: DefId, + trait_objects: &FxHashSet, + ) -> Option<(Ident, &'tcx hir::Ty<'tcx>)> { + let tcx = self.infcx.tcx; + match tcx.hir().get_if_local(def_id) { + Some(Node::ImplItem(impl_item)) => { + match tcx.hir().find_by_def_id(tcx.hir().get_parent_item(impl_item.hir_id())) { + Some(Node::Item(Item { + kind: ItemKind::Impl(hir::Impl { self_ty, .. }), + .. + })) => Some((impl_item.ident, self_ty)), + _ => None, + } + } + Some(Node::TraitItem(trait_item)) => { + let trait_did = tcx.hir().get_parent_item(trait_item.hir_id()); + match tcx.hir().find_by_def_id(trait_did) { + Some(Node::Item(Item { kind: ItemKind::Trait(..), .. })) => { + // The method being called is defined in the `trait`, but the `'static` + // obligation comes from the `impl`. Find that `impl` so that we can point + // at it in the suggestion. + let trait_did = trait_did.to_def_id(); + match tcx + .hir() + .trait_impls(trait_did) + .iter() + .filter_map(|&impl_did| { + match tcx.hir().get_if_local(impl_did.to_def_id()) { + Some(Node::Item(Item { + kind: ItemKind::Impl(hir::Impl { self_ty, .. }), + .. + })) if trait_objects.iter().all(|did| { + // FIXME: we should check `self_ty` against the receiver + // type in the `UnifyReceiver` context, but for now, use + // this imperfect proxy. This will fail if there are + // multiple `impl`s for the same trait like + // `impl Foo for Box` and `impl Foo for dyn Bar`. + // In that case, only the first one will get suggestions. + let mut traits = vec![]; + let mut hir_v = HirTraitObjectVisitor(&mut traits, *did); + hir_v.visit_ty(self_ty); + !traits.is_empty() + }) => + { + Some(self_ty) + } + _ => None, + } + }) + .next() + { + Some(self_ty) => Some((trait_item.ident, self_ty)), + _ => None, + } + } + _ => None, + } + } + _ => None, + } + } + /// Report an error because the universal region `fr` was required to outlive /// `outlived_fr` but it is not known to do so. For example: /// @@ -279,6 +350,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { }); debug!("report_region_error: category={:?} {:?} {:?}", category, cause, variance_info); + // Check if we can use one of the "nice region errors". if let (Some(f), Some(o)) = (self.to_error_region(fr), self.to_error_region(outlived_fr)) { let nice = NiceRegionError::new_from_span(self.infcx, cause.span, o, f); @@ -312,7 +384,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { self.report_fnmut_error(&errci, kind) } (ConstraintCategory::Assignment, true, false) - | (ConstraintCategory::CallArgument, true, false) => { + | (ConstraintCategory::CallArgument(_), true, false) => { let mut db = self.report_escaping_data_error(&errci); outlives_suggestion.intermediate_suggestion(self, &errci, &mut db); @@ -405,7 +477,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { /// ``` fn report_fnmut_error( &self, - errci: &ErrorConstraintInfo, + errci: &ErrorConstraintInfo<'tcx>, kind: ReturnConstraint, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { let ErrorConstraintInfo { outlived_fr, span, .. } = errci; @@ -486,7 +558,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { /// ``` fn report_escaping_data_error( &self, - errci: &ErrorConstraintInfo, + errci: &ErrorConstraintInfo<'tcx>, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { let ErrorConstraintInfo { span, category, .. } = errci; @@ -548,24 +620,28 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // Only show an extra note if we can find an 'error region' for both of the region // variables. This avoids showing a noisy note that just mentions 'synthetic' regions // that don't help the user understand the error. - if self.to_error_region(errci.fr).is_some() - && self.to_error_region(errci.outlived_fr).is_some() - { - let fr_region_name = self.give_region_a_name(errci.fr).unwrap(); - fr_region_name.highlight_region_name(&mut diag); - let outlived_fr_region_name = self.give_region_a_name(errci.outlived_fr).unwrap(); - outlived_fr_region_name.highlight_region_name(&mut diag); + match (self.to_error_region(errci.fr), self.to_error_region(errci.outlived_fr)) { + (Some(f), Some(o)) => { + self.maybe_suggest_constrain_dyn_trait_impl(&mut diag, f, o, category); - diag.span_label( - *span, - format!( - "{}requires that `{}` must outlive `{}`", - category.description(), - fr_region_name, - outlived_fr_region_name, - ), - ); + let fr_region_name = self.give_region_a_name(errci.fr).unwrap(); + fr_region_name.highlight_region_name(&mut diag); + let outlived_fr_region_name = self.give_region_a_name(errci.outlived_fr).unwrap(); + outlived_fr_region_name.highlight_region_name(&mut diag); + + diag.span_label( + *span, + format!( + "{}requires that `{}` must outlive `{}`", + category.description(), + fr_region_name, + outlived_fr_region_name, + ), + ); + } + _ => {} } + diag } @@ -586,7 +662,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { /// ``` fn report_general_error( &self, - errci: &ErrorConstraintInfo, + errci: &ErrorConstraintInfo<'tcx>, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { let ErrorConstraintInfo { fr, @@ -699,6 +775,99 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } } + fn maybe_suggest_constrain_dyn_trait_impl( + &self, + diag: &mut DiagnosticBuilder<'tcx, ErrorGuaranteed>, + f: Region<'tcx>, + o: Region<'tcx>, + category: &ConstraintCategory<'tcx>, + ) { + if !o.is_static() { + return; + } + + let tcx = self.infcx.tcx; + + let instance = if let ConstraintCategory::CallArgument(Some((fn_did, substs))) = category { + debug!(?fn_did, ?substs); + + // Only suggest this on function calls, not closures + let ty = tcx.type_of(fn_did); + debug!("ty: {:?}, ty.kind: {:?}", ty, ty.kind()); + if let ty::Closure(_, _) = ty.kind() { + return; + } + + if let Ok(Some(instance)) = ty::Instance::resolve( + tcx, + self.param_env, + *fn_did, + self.infcx.resolve_vars_if_possible(substs), + ) { + instance + } else { + return; + } + } else { + return; + }; + + let param = match find_param_with_region(tcx, f, o) { + Some(param) => param, + None => return, + }; + debug!(?param); + + let mut visitor = TraitObjectVisitor(FxHashSet::default()); + visitor.visit_ty(param.param_ty); + + if let Some((ident, self_ty)) = + self.get_impl_ident_and_self_ty_from_trait(instance.def_id(), &visitor.0) + { + self.suggest_constrain_dyn_trait_in_impl(diag, &visitor.0, ident, self_ty) + } else { + return; + }; + } + + #[instrument(skip(self, err), level = "debug")] + fn suggest_constrain_dyn_trait_in_impl( + &self, + err: &mut Diagnostic, + found_dids: &FxHashSet, + ident: Ident, + self_ty: &hir::Ty<'_>, + ) -> bool { + debug!("err: {:#?}", err); + let mut suggested = false; + for found_did in found_dids { + let mut traits = vec![]; + let mut hir_v = HirTraitObjectVisitor(&mut traits, *found_did); + hir_v.visit_ty(&self_ty); + debug!("trait spans found: {:?}", traits); + for span in &traits { + let mut multi_span: MultiSpan = vec![*span].into(); + multi_span.push_span_label( + *span, + "this has an implicit `'static` lifetime requirement".to_string(), + ); + multi_span.push_span_label( + ident.span, + "calling this method introduces the `impl`'s 'static` requirement".to_string(), + ); + err.span_note(multi_span, "the used `impl` has a `'static` requirement"); + err.span_suggestion_verbose( + span.shrink_to_hi(), + "consider relaxing the implicit `'static` requirement", + " + '_".to_string(), + Applicability::MaybeIncorrect, + ); + suggested = true; + } + } + suggested + } + fn suggest_adding_lifetime_params( &self, diag: &mut Diagnostic, diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index bf52b1be6782e..2cff12e3c8b83 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -938,7 +938,7 @@ pub(crate) struct MirTypeckRegionConstraints<'tcx> { pub(crate) member_constraints: MemberConstraintSet<'tcx, RegionVid>, - crate closure_bounds_mapping: + pub(crate) closure_bounds_mapping: FxHashMap, Span)>>, pub(crate) universe_causes: FxHashMap>, diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs index 29b3807a514bb..96b57b6cd2055 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs @@ -34,6 +34,7 @@ pub struct AnonymousParamInfo<'tcx> { // i32, which is the type of y but with the anonymous region replaced // with 'a, the corresponding bound region and is_first which is true if // the hir::Param is the first parameter in the function declaration. +#[instrument(skip(tcx), level = "debug")] pub fn find_param_with_region<'tcx>( tcx: TyCtxt<'tcx>, anon_region: Region<'tcx>, @@ -51,9 +52,19 @@ pub fn find_param_with_region<'tcx>( let hir_id = hir.local_def_id_to_hir_id(id.as_local()?); let body_id = hir.maybe_body_owned_by(hir_id)?; let body = hir.body(body_id); + + // Don't perform this on closures + match hir.get(hir_id) { + hir::Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure(..), .. }) => { + return None; + } + _ => {} + } + let owner_id = hir.body_owner(body_id); let fn_decl = hir.fn_decl_by_hir_id(owner_id).unwrap(); let poly_fn_sig = tcx.fn_sig(id); + let fn_sig = tcx.liberate_late_bound_regions(id, poly_fn_sig); body.params .iter() From ca9d72540b0f90dee4a090b362843e9a38606520 Mon Sep 17 00:00:00 2001 From: b-naber Date: Sun, 22 May 2022 17:07:35 +0200 Subject: [PATCH 4/6] update tests --- ...er-to-static-comparing-against-free.stderr | 15 +-- .../ui/nll/impl-dyn-trait-static-bound.rs | 116 ++++++++++++++++++ .../ui/nll/impl-dyn-trait-static-bound.stderr | 105 ++++++++++++++++ .../user-annotations/adt-nullary-enums.stderr | 16 +-- 4 files changed, 237 insertions(+), 15 deletions(-) create mode 100644 src/test/ui/nll/impl-dyn-trait-static-bound.rs create mode 100644 src/test/ui/nll/impl-dyn-trait-static-bound.stderr diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr index 30ef343b26123..3ab55b370c231 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr @@ -72,14 +72,15 @@ LL | | } error[E0597]: `a` does not live long enough --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:30:26 | -LL | let cell = Cell::new(&a); - | ----------^^- - | | | - | | borrowed value does not live long enough - | argument requires that `a` is borrowed for `'static` +LL | let cell = Cell::new(&a); + | ^^ borrowed value does not live long enough ... -LL | } - | - `a` dropped here while still borrowed +LL | / foo(cell, |cell_a, cell_x| { +LL | | cell_x.set(cell_a.get()); // forces 'a: 'x, implies 'a = 'static -> borrow error +LL | | }) + | |______- argument requires that `a` is borrowed for `'static` +LL | } + | - `a` dropped here while still borrowed error: aborting due to 2 previous errors diff --git a/src/test/ui/nll/impl-dyn-trait-static-bound.rs b/src/test/ui/nll/impl-dyn-trait-static-bound.rs new file mode 100644 index 0000000000000..ea835f2e05260 --- /dev/null +++ b/src/test/ui/nll/impl-dyn-trait-static-bound.rs @@ -0,0 +1,116 @@ +#![allow(dead_code)] +#![feature(nll)] + +mod foo { + trait OtherTrait<'a> {} + impl<'a> OtherTrait<'a> for &'a () {} + + trait ObjectTrait {} + trait MyTrait { + fn use_self(&self) -> &(); + } + trait Irrelevant {} + + impl MyTrait for dyn ObjectTrait { + fn use_self(&self) -> &() { panic!() } + } + impl Irrelevant for dyn ObjectTrait {} + + fn use_it<'a, T>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + val.use_self::() + //~^ ERROR borrowed data escapes outside + } +} + +mod bar { + trait ObjectTrait {} + trait MyTrait { + fn use_self(&self) -> &(); + } + trait Irrelevant {} + + impl MyTrait for dyn ObjectTrait { + fn use_self(&self) -> &() { panic!() } + } + impl Irrelevant for dyn ObjectTrait {} + + fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () { + val.use_self() + } +} + +mod baz { + trait ObjectTrait {} + trait MyTrait { + fn use_self(&self) -> &(); + } + trait Irrelevant {} + + impl MyTrait for Box { + fn use_self(&self) -> &() { panic!() } + } + impl Irrelevant for Box {} + + fn use_it<'a>(val: &'a Box) -> &'a () { + val.use_self() + } +} + +mod bat { + trait OtherTrait<'a> {} + impl<'a> OtherTrait<'a> for &'a () {} + + trait ObjectTrait {} + + impl dyn ObjectTrait { + fn use_self(&self) -> &() { panic!() } + } + + fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + val.use_self() + //~^ ERROR borrowed data escapes outside + } +} + +mod ban { + trait OtherTrait<'a> {} + impl<'a> OtherTrait<'a> for &'a () {} + + trait ObjectTrait {} + trait MyTrait { + fn use_self(&self) -> &() { panic!() } + } + trait Irrelevant { + fn use_self(&self) -> &() { panic!() } + } + + impl MyTrait for dyn ObjectTrait {} + + fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> { + val.use_self() + //~^ ERROR borrowed data escapes outside + } +} + +mod bal { + trait OtherTrait<'a> {} + impl<'a> OtherTrait<'a> for &'a () {} + + trait ObjectTrait {} + trait MyTrait { + fn use_self(&self) -> &() { panic!() } + } + trait Irrelevant { + fn use_self(&self) -> &() { panic!() } + } + + impl MyTrait for dyn ObjectTrait {} + impl Irrelevant for dyn ObjectTrait {} + + fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + MyTrait::use_self(val) + //~^ ERROR borrowed data escapes outside + } +} + +fn main() {} diff --git a/src/test/ui/nll/impl-dyn-trait-static-bound.stderr b/src/test/ui/nll/impl-dyn-trait-static-bound.stderr new file mode 100644 index 0000000000000..dd6b50839ef9d --- /dev/null +++ b/src/test/ui/nll/impl-dyn-trait-static-bound.stderr @@ -0,0 +1,105 @@ +error[E0521]: borrowed data escapes outside of function + --> $DIR/impl-dyn-trait-static-bound.rs:20:9 + | +LL | fn use_it<'a, T>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + | -- --- `val` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here +LL | val.use_self::() + | ^^^^^^^^^^^^^^^^^^^ + | | + | `val` escapes the function body here + | argument requires that `'a` must outlive `'static` + | +note: the used `impl` has a `'static` requirement + --> $DIR/impl-dyn-trait-static-bound.rs:14:32 + | +LL | impl MyTrait for dyn ObjectTrait { + | ^^^^^^^^^^^^^^ this has an implicit `'static` lifetime requirement +LL | fn use_self(&self) -> &() { panic!() } + | -------- calling this method introduces the `impl`'s 'static` requirement +help: consider relaxing the implicit `'static` requirement + | +LL | impl MyTrait for dyn ObjectTrait + '_ { + | ++++ + +error[E0521]: borrowed data escapes outside of function + --> $DIR/impl-dyn-trait-static-bound.rs:70:9 + | +LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + | -- --- `val` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here +LL | val.use_self() + | ^^^^^^^^^^^^^^ + | | + | `val` escapes the function body here + | argument requires that `'a` must outlive `'static` + | +note: the used `impl` has a `'static` requirement + --> $DIR/impl-dyn-trait-static-bound.rs:65:14 + | +LL | impl dyn ObjectTrait { + | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement +LL | fn use_self(&self) -> &() { panic!() } + | -------- calling this method introduces the `impl`'s 'static` requirement +help: consider relaxing the implicit `'static` requirement + | +LL | impl dyn ObjectTrait + '_ { + | ++++ + +error[E0521]: borrowed data escapes outside of function + --> $DIR/impl-dyn-trait-static-bound.rs:90:9 + | +LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> { + | -- --- `val` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here +LL | val.use_self() + | ^^^^^^^^^^^^^^ + | | + | `val` escapes the function body here + | argument requires that `'a` must outlive `'static` + | +note: the used `impl` has a `'static` requirement + --> $DIR/impl-dyn-trait-static-bound.rs:87:26 + | +LL | fn use_self(&self) -> &() { panic!() } + | -------- calling this method introduces the `impl`'s 'static` requirement +... +LL | impl MyTrait for dyn ObjectTrait {} + | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement +help: consider relaxing the implicit `'static` requirement + | +LL | impl MyTrait for dyn ObjectTrait + '_ {} + | ++++ + +error[E0521]: borrowed data escapes outside of function + --> $DIR/impl-dyn-trait-static-bound.rs:111:9 + | +LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + | -- --- `val` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here +LL | MyTrait::use_self(val) + | ^^^^^^^^^^^^^^^^^^^^^^ + | | + | `val` escapes the function body here + | argument requires that `'a` must outlive `'static` + | +note: the used `impl` has a `'static` requirement + --> $DIR/impl-dyn-trait-static-bound.rs:107:26 + | +LL | fn use_self(&self) -> &() { panic!() } + | -------- calling this method introduces the `impl`'s 'static` requirement +... +LL | impl MyTrait for dyn ObjectTrait {} + | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement +help: consider relaxing the implicit `'static` requirement + | +LL | impl MyTrait for dyn ObjectTrait + '_ {} + | ++++ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0521`. diff --git a/src/test/ui/nll/user-annotations/adt-nullary-enums.stderr b/src/test/ui/nll/user-annotations/adt-nullary-enums.stderr index bb70341222880..3326fa521fc9c 100644 --- a/src/test/ui/nll/user-annotations/adt-nullary-enums.stderr +++ b/src/test/ui/nll/user-annotations/adt-nullary-enums.stderr @@ -1,14 +1,14 @@ error[E0597]: `c` does not live long enough --> $DIR/adt-nullary-enums.rs:33:41 | -LL | SomeEnum::SomeVariant(Cell::new(&c)), - | ----------^^- - | | | - | | borrowed value does not live long enough - | argument requires that `c` is borrowed for `'static` -... -LL | } - | - `c` dropped here while still borrowed +LL | / combine( +LL | | SomeEnum::SomeVariant(Cell::new(&c)), + | | ^^ borrowed value does not live long enough +LL | | SomeEnum::SomeOtherVariant::>, +LL | | ); + | |_____- argument requires that `c` is borrowed for `'static` +LL | } + | - `c` dropped here while still borrowed error[E0597]: `c` does not live long enough --> $DIR/adt-nullary-enums.rs:41:41 From 99fa123f6619433d39a2e9f04d80c244fec17980 Mon Sep 17 00:00:00 2001 From: b-naber Date: Mon, 23 May 2022 09:50:32 +0200 Subject: [PATCH 5/6] bless existing test with compare-mode=nll and remove test --- ...ect-fn-ret-invariant-nll.krisskross.stderr | 4 +- ...project-fn-ret-invariant-nll.oneuse.stderr | 10 +- .../cache/project-fn-ret-invariant-nll.rs | 3 +- ...ject-fn-ret-invariant-nll.transmute.stderr | 2 +- .../async-await/issues/issue-72312.nll.stderr | 13 +- .../ui/nll/impl-dyn-trait-static-bound.rs | 116 ------------------ .../ui/nll/impl-dyn-trait-static-bound.stderr | 105 ---------------- ...rait-with-implicit-static-bound-nll.stderr | 50 ++++++++ 8 files changed, 66 insertions(+), 237 deletions(-) delete mode 100644 src/test/ui/nll/impl-dyn-trait-static-bound.rs delete mode 100644 src/test/ui/nll/impl-dyn-trait-static-bound.stderr diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant-nll.krisskross.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant-nll.krisskross.stderr index 231e98cf841f2..09119ea2bb5f9 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant-nll.krisskross.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant-nll.krisskross.stderr @@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/project-fn-ret-invariant-nll.rs:63:5 + --> $DIR/project-fn-ret-invariant-nll.rs:64:5 | LL | fn transmute<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { | -- -- lifetime `'b` defined here @@ -15,7 +15,7 @@ LL | (a, b) = help: see for more information about variance error: lifetime may not live long enough - --> $DIR/project-fn-ret-invariant-nll.rs:63:5 + --> $DIR/project-fn-ret-invariant-nll.rs:64:5 | LL | fn transmute<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { | -- -- lifetime `'b` defined here diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant-nll.oneuse.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant-nll.oneuse.stderr index 1dbfff6a8cdeb..266f3b99f9f30 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant-nll.oneuse.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant-nll.oneuse.stderr @@ -15,19 +15,19 @@ LL | let a = bar(f, x); = help: see for more information about variance error: lifetime may not live long enough - --> $DIR/project-fn-ret-invariant-nll.rs:47:13 + --> $DIR/project-fn-ret-invariant-nll.rs:46:13 | LL | fn baz<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { | -- -- lifetime `'b` defined here | | | lifetime `'a` defined here -... -LL | let b = bar(f, y); +LL | let f = foo; // <-- No consistent type can be inferred for `f` here. +LL | let a = bar(f, x); | ^^^^^^^^^ argument requires that `'b` must outlive `'a` | = help: consider adding the following bound: `'b: 'a` - = note: requirement occurs because of the type `Type<'_>`, which makes the generic argument `'_` invariant - = note: the struct `Type<'a>` is invariant over the parameter `'a` + = note: requirement occurs because of a function pointer to `foo` + = note: the function `foo` is invariant over the parameter `'a` = help: see for more information about variance help: `'a` and `'b` must be the same: replace one with the other diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant-nll.rs b/src/test/ui/associated-types/cache/project-fn-ret-invariant-nll.rs index 6cd5c6417a914..15bf38dabc060 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant-nll.rs +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant-nll.rs @@ -44,7 +44,8 @@ fn baz<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { fn baz<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { let f = foo; // <-- No consistent type can be inferred for `f` here. let a = bar(f, x); //[oneuse]~ ERROR lifetime may not live long enough - let b = bar(f, y); //[oneuse]~ ERROR lifetime may not live long enough + //[oneuse]~^ ERROR lifetime may not live long enough + let b = bar(f, y); (a, b) } diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant-nll.transmute.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant-nll.transmute.stderr index 352914f020c2c..56f081529997f 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant-nll.transmute.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant-nll.transmute.stderr @@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/project-fn-ret-invariant-nll.rs:56:5 + --> $DIR/project-fn-ret-invariant-nll.rs:57:5 | LL | fn baz<'a, 'b>(x: Type<'a>) -> Type<'static> { | -- lifetime `'a` defined here diff --git a/src/test/ui/async-await/issues/issue-72312.nll.stderr b/src/test/ui/async-await/issues/issue-72312.nll.stderr index 53b2c931cceab..02e47721e0cf9 100644 --- a/src/test/ui/async-await/issues/issue-72312.nll.stderr +++ b/src/test/ui/async-await/issues/issue-72312.nll.stderr @@ -1,5 +1,5 @@ error[E0521]: borrowed data escapes outside of associated function - --> $DIR/issue-72312.rs:20:24 + --> $DIR/issue-72312.rs:20:9 | LL | pub async fn start(&self) { | ----- @@ -7,18 +7,17 @@ LL | pub async fn start(&self) { | `self` is a reference that is only valid in the associated function body | let's call the lifetime of this reference `'1` ... -LL | require_static(async move { - | ________________________^ +LL | / require_static(async move { LL | | LL | | LL | | LL | | LL | | &self; LL | | }); - | | ^ - | | | - | |_________`self` escapes the associated function body here - | argument requires that `'1` must outlive `'static` + | | ^ + | | | + | |__________`self` escapes the associated function body here + | argument requires that `'1` must outlive `'static` error: aborting due to previous error diff --git a/src/test/ui/nll/impl-dyn-trait-static-bound.rs b/src/test/ui/nll/impl-dyn-trait-static-bound.rs deleted file mode 100644 index ea835f2e05260..0000000000000 --- a/src/test/ui/nll/impl-dyn-trait-static-bound.rs +++ /dev/null @@ -1,116 +0,0 @@ -#![allow(dead_code)] -#![feature(nll)] - -mod foo { - trait OtherTrait<'a> {} - impl<'a> OtherTrait<'a> for &'a () {} - - trait ObjectTrait {} - trait MyTrait { - fn use_self(&self) -> &(); - } - trait Irrelevant {} - - impl MyTrait for dyn ObjectTrait { - fn use_self(&self) -> &() { panic!() } - } - impl Irrelevant for dyn ObjectTrait {} - - fn use_it<'a, T>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { - val.use_self::() - //~^ ERROR borrowed data escapes outside - } -} - -mod bar { - trait ObjectTrait {} - trait MyTrait { - fn use_self(&self) -> &(); - } - trait Irrelevant {} - - impl MyTrait for dyn ObjectTrait { - fn use_self(&self) -> &() { panic!() } - } - impl Irrelevant for dyn ObjectTrait {} - - fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () { - val.use_self() - } -} - -mod baz { - trait ObjectTrait {} - trait MyTrait { - fn use_self(&self) -> &(); - } - trait Irrelevant {} - - impl MyTrait for Box { - fn use_self(&self) -> &() { panic!() } - } - impl Irrelevant for Box {} - - fn use_it<'a>(val: &'a Box) -> &'a () { - val.use_self() - } -} - -mod bat { - trait OtherTrait<'a> {} - impl<'a> OtherTrait<'a> for &'a () {} - - trait ObjectTrait {} - - impl dyn ObjectTrait { - fn use_self(&self) -> &() { panic!() } - } - - fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { - val.use_self() - //~^ ERROR borrowed data escapes outside - } -} - -mod ban { - trait OtherTrait<'a> {} - impl<'a> OtherTrait<'a> for &'a () {} - - trait ObjectTrait {} - trait MyTrait { - fn use_self(&self) -> &() { panic!() } - } - trait Irrelevant { - fn use_self(&self) -> &() { panic!() } - } - - impl MyTrait for dyn ObjectTrait {} - - fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> { - val.use_self() - //~^ ERROR borrowed data escapes outside - } -} - -mod bal { - trait OtherTrait<'a> {} - impl<'a> OtherTrait<'a> for &'a () {} - - trait ObjectTrait {} - trait MyTrait { - fn use_self(&self) -> &() { panic!() } - } - trait Irrelevant { - fn use_self(&self) -> &() { panic!() } - } - - impl MyTrait for dyn ObjectTrait {} - impl Irrelevant for dyn ObjectTrait {} - - fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { - MyTrait::use_self(val) - //~^ ERROR borrowed data escapes outside - } -} - -fn main() {} diff --git a/src/test/ui/nll/impl-dyn-trait-static-bound.stderr b/src/test/ui/nll/impl-dyn-trait-static-bound.stderr deleted file mode 100644 index dd6b50839ef9d..0000000000000 --- a/src/test/ui/nll/impl-dyn-trait-static-bound.stderr +++ /dev/null @@ -1,105 +0,0 @@ -error[E0521]: borrowed data escapes outside of function - --> $DIR/impl-dyn-trait-static-bound.rs:20:9 - | -LL | fn use_it<'a, T>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { - | -- --- `val` is a reference that is only valid in the function body - | | - | lifetime `'a` defined here -LL | val.use_self::() - | ^^^^^^^^^^^^^^^^^^^ - | | - | `val` escapes the function body here - | argument requires that `'a` must outlive `'static` - | -note: the used `impl` has a `'static` requirement - --> $DIR/impl-dyn-trait-static-bound.rs:14:32 - | -LL | impl MyTrait for dyn ObjectTrait { - | ^^^^^^^^^^^^^^ this has an implicit `'static` lifetime requirement -LL | fn use_self(&self) -> &() { panic!() } - | -------- calling this method introduces the `impl`'s 'static` requirement -help: consider relaxing the implicit `'static` requirement - | -LL | impl MyTrait for dyn ObjectTrait + '_ { - | ++++ - -error[E0521]: borrowed data escapes outside of function - --> $DIR/impl-dyn-trait-static-bound.rs:70:9 - | -LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { - | -- --- `val` is a reference that is only valid in the function body - | | - | lifetime `'a` defined here -LL | val.use_self() - | ^^^^^^^^^^^^^^ - | | - | `val` escapes the function body here - | argument requires that `'a` must outlive `'static` - | -note: the used `impl` has a `'static` requirement - --> $DIR/impl-dyn-trait-static-bound.rs:65:14 - | -LL | impl dyn ObjectTrait { - | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement -LL | fn use_self(&self) -> &() { panic!() } - | -------- calling this method introduces the `impl`'s 'static` requirement -help: consider relaxing the implicit `'static` requirement - | -LL | impl dyn ObjectTrait + '_ { - | ++++ - -error[E0521]: borrowed data escapes outside of function - --> $DIR/impl-dyn-trait-static-bound.rs:90:9 - | -LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> { - | -- --- `val` is a reference that is only valid in the function body - | | - | lifetime `'a` defined here -LL | val.use_self() - | ^^^^^^^^^^^^^^ - | | - | `val` escapes the function body here - | argument requires that `'a` must outlive `'static` - | -note: the used `impl` has a `'static` requirement - --> $DIR/impl-dyn-trait-static-bound.rs:87:26 - | -LL | fn use_self(&self) -> &() { panic!() } - | -------- calling this method introduces the `impl`'s 'static` requirement -... -LL | impl MyTrait for dyn ObjectTrait {} - | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement -help: consider relaxing the implicit `'static` requirement - | -LL | impl MyTrait for dyn ObjectTrait + '_ {} - | ++++ - -error[E0521]: borrowed data escapes outside of function - --> $DIR/impl-dyn-trait-static-bound.rs:111:9 - | -LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { - | -- --- `val` is a reference that is only valid in the function body - | | - | lifetime `'a` defined here -LL | MyTrait::use_self(val) - | ^^^^^^^^^^^^^^^^^^^^^^ - | | - | `val` escapes the function body here - | argument requires that `'a` must outlive `'static` - | -note: the used `impl` has a `'static` requirement - --> $DIR/impl-dyn-trait-static-bound.rs:107:26 - | -LL | fn use_self(&self) -> &() { panic!() } - | -------- calling this method introduces the `impl`'s 'static` requirement -... -LL | impl MyTrait for dyn ObjectTrait {} - | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement -help: consider relaxing the implicit `'static` requirement - | -LL | impl MyTrait for dyn ObjectTrait + '_ {} - | ++++ - -error: aborting due to 4 previous errors - -For more information about this error, try `rustc --explain E0521`. diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-nll.stderr b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-nll.stderr index 38731ea895533..5d9c7077fa109 100644 --- a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-nll.stderr +++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-nll.stderr @@ -10,6 +10,18 @@ LL | val.use_self::() | | | `val` escapes the function body here | argument requires that `'a` must outlive `'static` + | +note: the used `impl` has a `'static` requirement + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-nll.rs:19:32 + | +LL | impl MyTrait for dyn ObjectTrait { + | ^^^^^^^^^^^^^^ this has an implicit `'static` lifetime requirement +LL | fn use_self(&self) -> &() { panic!() } + | -------- calling this method introduces the `impl`'s 'static` requirement +help: consider relaxing the implicit `'static` requirement + | +LL | impl MyTrait for dyn ObjectTrait + '_ { + | ++++ error[E0521]: borrowed data escapes outside of function --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-nll.rs:74:9 @@ -23,6 +35,18 @@ LL | val.use_self() | | | `val` escapes the function body here | argument requires that `'a` must outlive `'static` + | +note: the used `impl` has a `'static` requirement + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-nll.rs:69:14 + | +LL | impl dyn ObjectTrait { + | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement +LL | fn use_self(&self) -> &() { panic!() } + | -------- calling this method introduces the `impl`'s 'static` requirement +help: consider relaxing the implicit `'static` requirement + | +LL | impl dyn ObjectTrait + '_ { + | ++++ error[E0521]: borrowed data escapes outside of function --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-nll.rs:94:9 @@ -36,6 +60,19 @@ LL | val.use_self() | | | `val` escapes the function body here | argument requires that `'a` must outlive `'static` + | +note: the used `impl` has a `'static` requirement + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-nll.rs:91:26 + | +LL | fn use_self(&self) -> &() { panic!() } + | -------- calling this method introduces the `impl`'s 'static` requirement +... +LL | impl MyTrait for dyn ObjectTrait {} + | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement +help: consider relaxing the implicit `'static` requirement + | +LL | impl MyTrait for dyn ObjectTrait + '_ {} + | ++++ error[E0521]: borrowed data escapes outside of function --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-nll.rs:114:9 @@ -49,6 +86,19 @@ LL | MyTrait::use_self(val) | | | `val` escapes the function body here | argument requires that `'a` must outlive `'static` + | +note: the used `impl` has a `'static` requirement + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-nll.rs:110:26 + | +LL | fn use_self(&self) -> &() { panic!() } + | -------- calling this method introduces the `impl`'s 'static` requirement +... +LL | impl MyTrait for dyn ObjectTrait {} + | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement +help: consider relaxing the implicit `'static` requirement + | +LL | impl MyTrait for dyn ObjectTrait + '_ {} + | ++++ error: aborting due to 4 previous errors From 3c6c8d5a8dbf4db20450ed5793ef35f29c13466c Mon Sep 17 00:00:00 2001 From: b-naber Date: Wed, 25 May 2022 23:32:27 +0200 Subject: [PATCH 6/6] rebase, use Ty in CallArgument and re-insert static_assert_size on ConstraintCategory --- .../src/diagnostics/region_errors.rs | 17 ++++++++-------- compiler/rustc_borrowck/src/type_check/mod.rs | 20 +++++++------------ compiler/rustc_middle/src/mir/query.rs | 10 ++++++++-- compiler/rustc_middle/src/ty/impls_ty.rs | 4 ++-- 4 files changed, 26 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index a637f0613d172..48b8230857a69 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -788,7 +788,11 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let tcx = self.infcx.tcx; - let instance = if let ConstraintCategory::CallArgument(Some((fn_did, substs))) = category { + let instance = if let ConstraintCategory::CallArgument(Some(func_ty)) = category { + let (fn_did, substs) = match func_ty.kind() { + ty::FnDef(fn_did, substs) => (fn_did, substs), + _ => return, + }; debug!(?fn_did, ?substs); // Only suggest this on function calls, not closures @@ -821,13 +825,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let mut visitor = TraitObjectVisitor(FxHashSet::default()); visitor.visit_ty(param.param_ty); - if let Some((ident, self_ty)) = - self.get_impl_ident_and_self_ty_from_trait(instance.def_id(), &visitor.0) - { - self.suggest_constrain_dyn_trait_in_impl(diag, &visitor.0, ident, self_ty) - } else { - return; - }; + let Some((ident, self_ty)) = + self.get_impl_ident_and_self_ty_from_trait(instance.def_id(), &visitor.0) else {return}; + + self.suggest_constrain_dyn_trait_in_impl(diag, &visitor.0, ident, self_ty); } #[instrument(skip(self, err), level = "debug")] diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 2cff12e3c8b83..4a2b2942008b8 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1418,7 +1418,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ref args, ref destination, from_hir_call, - fn_span, + target, .. } => { self.check_operand(func, term_location); @@ -1427,9 +1427,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } let func_ty = func.ty(body, tcx); - debug!("check_terminator: call, func_ty={:?}", func_ty); debug!("func_ty.kind: {:?}", func_ty.kind()); - debug!(?fn_span); + let sig = match func_ty.kind() { ty::FnDef(..) | ty::FnPtr(_) => func_ty.fn_sig(tcx), _ => { @@ -1444,7 +1443,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ); debug!(?sig); let sig = self.normalize(sig, term_location); - self.check_call_dest(body, term, &sig, destination, target, term_location); + self.check_call_dest(body, term, &sig, *destination, target, term_location); self.prove_predicates( sig.inputs_and_output @@ -1604,24 +1603,19 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { span_mirbug!(self, term, "call to {:?} with wrong # of args", sig); } - let call_arg = if let TerminatorKind::Call { func, .. } = &term.kind { - let func_ty = func.ty(body, self.infcx.tcx); - if let ty::FnDef(fn_did, substs) = func_ty.kind() { - Some((*fn_did, *substs)) - } else { - None - } + let func_ty = if let TerminatorKind::Call { func, .. } = &term.kind { + Some(func.ty(body, self.infcx.tcx)) } else { None }; - debug!(?call_arg); + debug!(?func_ty); for (n, (fn_arg, op_arg)) in iter::zip(sig.inputs(), args).enumerate() { let op_arg_ty = op_arg.ty(body, self.tcx()); let op_arg_ty = self.normalize(op_arg_ty, term_location); let category = if from_hir_call { - ConstraintCategory::CallArgument(call_arg) + ConstraintCategory::CallArgument(func_ty) } else { ConstraintCategory::Boring }; diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index 4f71e3a8234fa..01945b543b14b 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -1,7 +1,7 @@ //! Values computed by queries that use MIR. use crate::mir::{self, Body, Promoted}; -use crate::ty::{self, subst::SubstsRef, OpaqueHiddenType, Ty, TyCtxt}; +use crate::ty::{self, OpaqueHiddenType, Ty, TyCtxt}; use rustc_data_structures::stable_map::FxHashMap; use rustc_data_structures::vec_map::VecMap; use rustc_errors::ErrorGuaranteed; @@ -341,6 +341,10 @@ pub struct ClosureOutlivesRequirement<'tcx> { pub category: ConstraintCategory<'tcx>, } +// Make sure this enum doesn't unintentionally grow +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] +rustc_data_structures::static_assert_size!(ConstraintCategory<'_>, 16); + /// Outlives-constraints can be categorized to determine whether and why they /// are interesting (for error reporting). Order of variants indicates sort /// order of the category, thereby influencing diagnostic output. @@ -360,7 +364,9 @@ pub enum ConstraintCategory<'tcx> { /// /// We try to get the category that the closure used when reporting this. ClosureBounds, - CallArgument(Option<(DefId, SubstsRef<'tcx>)>), + + /// Contains the function type if available. + CallArgument(Option>), CopyBound, SizedBound, Assignment, diff --git a/compiler/rustc_middle/src/ty/impls_ty.rs b/compiler/rustc_middle/src/ty/impls_ty.rs index d6b5e9ddfbd6f..42e5a05d63b76 100644 --- a/compiler/rustc_middle/src/ty/impls_ty.rs +++ b/compiler/rustc_middle/src/ty/impls_ty.rs @@ -135,8 +135,8 @@ impl<'a> HashStable> for ty::RegionKind { ty::RePlaceholder(p) => { p.hash_stable(hcx, hasher); } - ty::ReVar(reg_vid) => { - reg_vid.hash_stable(hcx, hasher); + ty::ReVar(reg) => { + reg.hash_stable(hcx, hasher); } } }