From f9a9a5ebd607077f18482e8f3bdb39d83a07b146 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 21 Feb 2024 06:33:54 +0000 Subject: [PATCH] Account for more cases --- .../src/diagnostics/region_errors.rs | 21 +++++---- ...issue-80701-dyn-trait-static-obligation.rs | 47 +++++++++++++++++++ ...e-80701-dyn-trait-static-obligation.stderr | 24 ++++++++++ 3 files changed, 82 insertions(+), 10 deletions(-) create mode 100644 tests/ui/lifetimes/issue-80701-dyn-trait-static-obligation.rs create mode 100644 tests/ui/lifetimes/issue-80701-dyn-trait-static-obligation.stderr diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 0e6ced50df630..5649759e544d3 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -496,7 +496,11 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } }; - self.explain_impl_static_obligation(&mut diag, cause.code(), outlived_fr); + if let ConstraintCategory::CallArgument(Some(ty)) = category { + self.explain_impl_static_obligation(&mut diag, ty, cause.span, outlived_fr); + } else if let ObligationCauseCode::MethodCallConstraint(ty, call_span) = cause.code() { + self.explain_impl_static_obligation(&mut diag, *ty, *call_span, outlived_fr); + } match variance_info { ty::VarianceDiagInfo::None => {} @@ -618,14 +622,11 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { fn explain_impl_static_obligation( &self, diag: &mut DiagnosticBuilder<'_>, - code: &ObligationCauseCode<'tcx>, + ty: Ty<'tcx>, + call_span: Span, outlived_fr: RegionVid, ) { let tcx = self.infcx.tcx; - debug!(?code); - let ObligationCauseCode::MethodCallConstraint(ty, call_span) = code else { - return; - }; let ty::FnDef(def_id, args) = ty.kind() else { return; }; @@ -719,7 +720,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { if let ty::Ref(region, _, _) = self .infcx .instantiate_binder_with_fresh_vars( - *call_span, + call_span, BoundRegionConversionTime::FnCall, tcx.fn_sig(def_id).instantiate_identity().inputs().map_bound(|inputs| inputs[0]), ) @@ -801,10 +802,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let span: MultiSpan = predicates.into(); diag.span_note(span, format!("the `impl` on `{ty}` has {a_static_lt}")); } - if new_primary_span && diag.span.primary_span() != Some(*call_span) { - diag.replace_span_with(*call_span, false); + if new_primary_span && diag.span.primary_span() != Some(call_span) { + diag.replace_span_with(call_span, false); diag.span_label( - *call_span, + call_span, "calling this method introduces a `'static` lifetime requirement", ); } diff --git a/tests/ui/lifetimes/issue-80701-dyn-trait-static-obligation.rs b/tests/ui/lifetimes/issue-80701-dyn-trait-static-obligation.rs new file mode 100644 index 0000000000000..864cdea76b4bd --- /dev/null +++ b/tests/ui/lifetimes/issue-80701-dyn-trait-static-obligation.rs @@ -0,0 +1,47 @@ +use std::cell::*; + +#[derive(Default)] +struct Test { + pub foo: u32, +} + +trait FooSetter { + fn set_foo(&mut self, value: u32); +} + +impl FooSetter for Test { + fn set_foo(&mut self, value: u32) { + self.foo = value; + } +} + +trait BaseSetter{ + fn set(&mut self, value: u32); +} +impl BaseSetter for dyn FooSetter { + fn set(&mut self, value: u32){ + self.set_foo(value); + } +} + +struct TestHolder<'a> { + pub holder: Option>, +} + +impl <'a>TestHolder<'a>{ + pub fn test_foo(&self){ + self.holder.as_ref().unwrap().borrow_mut().set(20); + //~^ ERROR borrowed data escapes outside of method + } +} + +fn main() { + let mut test = Test::default(); + test.foo = 10; + { + let holder = TestHolder { holder: Some(RefCell::from(&mut test))}; + + holder.test_foo(); + } + test.foo = 30; +} diff --git a/tests/ui/lifetimes/issue-80701-dyn-trait-static-obligation.stderr b/tests/ui/lifetimes/issue-80701-dyn-trait-static-obligation.stderr new file mode 100644 index 0000000000000..f83af12048bad --- /dev/null +++ b/tests/ui/lifetimes/issue-80701-dyn-trait-static-obligation.stderr @@ -0,0 +1,24 @@ +error[E0521]: borrowed data escapes outside of method + --> $DIR/issue-80701-dyn-trait-static-obligation.rs:33:8 + | +LL | impl <'a>TestHolder<'a>{ + | -- lifetime `'a` defined here +LL | pub fn test_foo(&self){ + | ----- `self` is a reference that is only valid in the method body +LL | self.holder.as_ref().unwrap().borrow_mut().set(20); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `self` escapes the method body here + | argument requires that `'a` must outlive `'static` + | + = note: requirement occurs because of a mutable reference to `dyn FooSetter` + = note: mutable references are invariant over their type parameter + = help: see for more information about variance +help: consider relaxing the implicit `'static` requirement on the impl + | +LL | impl BaseSetter for dyn FooSetter + '_ { + | ++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0521`.