Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 45 additions & 13 deletions compiler/rustc_borrowck/src/universal_regions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -516,21 +516,53 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
// Converse of above, if this is a function/closure then the late-bound regions declared
// on its signature are local.
//
// We manually loop over `bound_inputs_and_output` instead of using
// `for_each_late_bound_region_in_item` as we may need to add the otherwise
// implicit `ClosureEnv` region.
// For closures/coroutines, we manually loop over `bound_inputs_and_output` instead of
// using `for_each_late_bound_region_in_item` as we may need to add the otherwise
// implicit `ClosureEnv` region. For regular functions, we need to use
// `for_each_late_bound_region_in_item` to ensure we capture all late-bound regions,
// including those that don't appear in the inputs/output (e.g., unused lifetime parameters).
let bound_inputs_and_output = self.compute_inputs_and_output(&indices, defining_ty);
for (idx, bound_var) in bound_inputs_and_output.bound_vars().iter().enumerate() {
if let ty::BoundVariableKind::Region(kind) = bound_var {
let kind = ty::LateParamRegionKind::from_bound(ty::BoundVar::from_usize(idx), kind);
let r = ty::Region::new_late_param(self.infcx.tcx, self.mir_def.to_def_id(), kind);
let region_vid = {
let name = r.get_name_or_anon(self.infcx.tcx);
self.infcx.next_nll_region_var(FR, || RegionCtxt::LateBound(name))
};
match defining_ty {
DefiningTy::Closure(..)
| DefiningTy::Coroutine(..)
| DefiningTy::CoroutineClosure(..) => {
// For closures/coroutines, iterate over bound_vars to include implicit regions.
for (idx, bound_var) in bound_inputs_and_output.bound_vars().iter().enumerate() {
if let ty::BoundVariableKind::Region(kind) = bound_var {
let kind = ty::LateParamRegionKind::from_bound(
ty::BoundVar::from_usize(idx),
kind,
);
let r = ty::Region::new_late_param(
self.infcx.tcx,
self.mir_def.to_def_id(),
kind,
);
let region_vid = {
let name = r.get_name_or_anon(self.infcx.tcx);
self.infcx.next_nll_region_var(FR, || RegionCtxt::LateBound(name))
};

debug!(?region_vid);
indices.insert_late_bound_region(r, region_vid.as_var());
}
}
}
DefiningTy::FnDef(..) => {
// For functions, use for_each_late_bound_region_in_item to ensure we capture
// all late-bound regions, including those that don't appear in inputs/output.
for_each_late_bound_region_in_item(self.infcx.tcx, self.mir_def, |r| {
let region_vid = {
let name = r.get_name_or_anon(self.infcx.tcx);
self.infcx.next_nll_region_var(FR, || RegionCtxt::LateBound(name))
};

debug!(?region_vid);
indices.insert_late_bound_region(r, region_vid.as_var());
debug!(?region_vid);
indices.insert_late_bound_region(r, region_vid.as_var());
});
}
DefiningTy::Const(..) | DefiningTy::InlineConst(..) | DefiningTy::GlobalAsm(..) => {
// These don't have late-bound regions.
}
}
let inputs_and_output = self.infcx.replace_bound_regions_with_nll_infer_vars(
Expand Down
6 changes: 0 additions & 6 deletions tests/crashes/135845.rs

This file was deleted.

29 changes: 29 additions & 0 deletions tests/ui/lifetimes/late-bound-misuse-issue-135845.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Regression test for issue #135845
// Ensure we don't ICE when a lifetime parameter from a function
// is incorrectly used in an expression.

struct S<'a, T: ?Sized>(&'a T);

fn b<'a>() -> S<'static, _> {
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types
S::<'a>(&0)
}

fn static_to_a_to_static_through_ref_in_tuple<'a>(x: &'a u32) -> &'a _ {
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types
let (ref y, _z): (&'a u32, u32) = (&22, 44);
*y
}

fn opt_str2<'a>(maybestr: &'a Option<String>) -> &'a _ {
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types
match *maybestr {
None => "(none)",
Some(ref s) => {
let s: &'a str = s;
s
}
}
}

fn main() {}
39 changes: 39 additions & 0 deletions tests/ui/lifetimes/late-bound-misuse-issue-135845.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
--> $DIR/late-bound-misuse-issue-135845.rs:7:26
|
LL | fn b<'a>() -> S<'static, _> {
| ^ not allowed in type signatures
|
help: replace with the correct return type
|
LL - fn b<'a>() -> S<'static, _> {
LL + fn b<'a>() -> S<'_, i32> {
|

error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
--> $DIR/late-bound-misuse-issue-135845.rs:12:70
|
LL | fn static_to_a_to_static_through_ref_in_tuple<'a>(x: &'a u32) -> &'a _ {
| ^ not allowed in type signatures
|
help: replace with the correct return type
|
LL - fn static_to_a_to_static_through_ref_in_tuple<'a>(x: &'a u32) -> &'a _ {
LL + fn static_to_a_to_static_through_ref_in_tuple<'a>(x: &'a u32) -> &u32 {
|

error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
--> $DIR/late-bound-misuse-issue-135845.rs:18:54
|
LL | fn opt_str2<'a>(maybestr: &'a Option<String>) -> &'a _ {
| ^ not allowed in type signatures
|
help: replace with the correct return type
|
LL - fn opt_str2<'a>(maybestr: &'a Option<String>) -> &'a _ {
LL + fn opt_str2<'a>(maybestr: &'a Option<String>) -> &str {
|

error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0121`.
Loading