Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Abort on potential infinite recursion in type_must_outlive (#25954) #26489

Closed
wants to merge 3 commits into from

Conversation

robertg
Copy link

@robertg robertg commented Jun 22, 2015

Display E0399 and stop recursing in type_must_outlive if a previous duplicate function application was encountered, to prevent a stack overflow.

This is my initial approach: Declare (ty, region, origin.span()) to define a distinct type_must_outlive function application, and use a HashSet to ensure no duplicate function applications occur.

Closes: #25954

Display E0399 and stop recursing in type_must_outlive if a previous
function application was encountered.
@rust-highfive
Copy link
Collaborator

Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @pcwalton (or someone else) soon.

If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. The way Github handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes.

Please see the contribution instructions for more information.

@robertg robertg changed the title Abort on recursion in type_must_outlive (#25954) Abort on potential infinite recursion in type_must_outlive (#25954) Jun 22, 2015
@arielb1
Copy link
Contributor

arielb1 commented Jun 22, 2015

Test please. I'm quite sure you need a recursion limit, not a loop check (the example creates a non-regular type via upvars).

@robertg
Copy link
Author

robertg commented Jun 22, 2015

@arielb1 I added a compile-fail-test. Are there some examples in the codebase utilizing recursion limits (does it use a function depth constant?). I think figuring out how to detect a loop in the 'region type graph' should be our goal, with using a recursion limit as a last resort.

@alexcrichton
Copy link
Member

r? @nikomatsakis or @arielb1

@@ -95,6 +95,7 @@ use middle::ty::{self, ClosureTyper, ReScope, Ty, MethodCall};
use middle::infer::{self, GenericKind};
use middle::pat_util;

use std::collections::HashSet;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: use FnvHashSet (that's util::nodemap::FnvHashSet).

@arielb1
Copy link
Contributor

arielb1 commented Jun 24, 2015

As an approach, I would prefer to check for closure representability (see ty::check_representable) rather than this explicit check.

type_must_outlive needs to be coinductive, through (is this right, @nikomatsakis?) - this should regionck

struct B<'a, F: Fn()+'a>(&'a F);

fn main() {
 let mut p = B(std::mem::zeroed());
 p.0 = &||{p.0;};
}

as it is a non-borrowcking sugaring of

#![feature(unboxed_closures,core)]

use std::cell::Cell;

struct B<'a, F: FnOnce()+'a>(Cell<Option<&'a F>>);

struct Closure<'a> {
    arg: B<'a, Closure<'a>>
}

impl<'a> FnOnce<()> for Closure<'a> {
    type Output = ();
    extern "rust-call" fn call_once(self, args: ()) {}
}

fn main() {
 let (mut p, mut cls);
 p = B(Cell::new(None));
 cls = Closure { arg: p };
 cls.arg.0.set(Some(&cls));
}

@bors
Copy link
Contributor

bors commented Jun 27, 2015

☔ The latest upstream changes (presumably #26575) made this pull request unmergeable. Please resolve the merge conflicts.

@nikomatsakis
Copy link
Contributor

Sorry, last week was the work week, and this week I'm on vacation. I'll try to read over the code/comments this week though. I will say that one of the RFCs I am hoping to propose once I get back makes this point about recursion moot.

@nikomatsakis
Copy link
Contributor

So, I'm in the process of preparing an RFC and PR that does a big overhaul to type_must_outlive, with the aim of fixing some soundness problems. As part of that, it makes infinite recursion impossible. Therefore, I'm inclined to close this PR in favor of that solution. Seem OK?

@robertg
Copy link
Author

robertg commented Jul 9, 2015

Yes.

@robertg robertg closed this Jul 9, 2015
@nikomatsakis
Copy link
Contributor

Hmm, actually, I was mistaken. The problem this PR aims to correct is not fixed by the patches I've been working on, or at least not the ones I was thining of. However, it IS fixed by a separate PR:

#27087

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants