Skip to content

Commit

Permalink
Account for more cases
Browse files Browse the repository at this point in the history
  • Loading branch information
estebank committed Feb 21, 2024
1 parent 0211233 commit 20e6a6c
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 10 deletions.
21 changes: 11 additions & 10 deletions compiler/rustc_borrowck/src/diagnostics/region_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 => {}
Expand Down Expand Up @@ -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;
};
Expand Down Expand Up @@ -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]),
)
Expand Down Expand Up @@ -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",
);
}
Expand Down
47 changes: 47 additions & 0 deletions tests/ui/lifetimes/dyn-trait-static-obligation.rs
Original file line number Diff line number Diff line change
@@ -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<RefCell<&'a mut dyn FooSetter>>,
}

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;
}
24 changes: 24 additions & 0 deletions tests/ui/lifetimes/dyn-trait-static-obligation.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
error[E0521]: borrowed data escapes outside of method
--> $DIR/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 <https://doc.rust-lang.org/nomicon/subtyping.html> 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`.

0 comments on commit 20e6a6c

Please sign in to comment.