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

infer outlives doesn't work across crates #51858

Closed
nikomatsakis opened this issue Jun 27, 2018 · 2 comments
Closed

infer outlives doesn't work across crates #51858

nikomatsakis opened this issue Jun 27, 2018 · 2 comments
Labels
A-edition-2018 Area: The 2018 edition C-enhancement Category: An issue proposing an enhancement or a PR with one. E-mentor Call for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion. F-rust_2018_preview `#![feature(rust_2018_preview)]` T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@nikomatsakis
Copy link
Contributor

This example fails to compile:

#![feature(infer_outlives_requirements)]

struct Bar<'a, T> {
    f: std::slice::IterMut<'a, T>
}

fn main() { }

however this purely intra-crate example works:

#![feature(infer_outlives_requirements)]

struct Foo<'a, T: 'a> {
    x: &'a T
}

struct Bar<'a, T> {
    f: Foo<'a, T>
}

fn main() { }

cc @toidiu

@nikomatsakis nikomatsakis added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Jun 27, 2018
@toidiu
Copy link
Contributor

toidiu commented Jun 28, 2018

Going to run the error scenario locally to better debug the issue.

@nikomatsakis
Copy link
Contributor Author

OK I think I see the problem.

First, to explain what I expect to happen:

When we are inferred the outlives for Bar, I expect us to see that std::slice::IterMut<'a, T> requires that T: 'a must hold, and hence infer that as an outlives requirement on Bar. This works locally but not across crates.

How to fix

I believe the problem is centered on this line:

if let Some(explicit_predicates) = explicit_map.get(def_id) {

In particular, this is part of the function that handles the case where we see a reference to a struct lke IterMut<'a, T>. It's supposed to be looking up the "explicit predicates" on that struct. That is fine for crate-local things, but for cross-crate things, inference is already complete, so we can just lookup the full set of predicates.

I think what we want is to rework the "explicit predicates map" setup. Currently, we do a kind of pre-pass that populates this map:

let exp = explicit::explicit_predicates(tcx, crate_num);

I think we should populate the map lazilly instead. I would think it should be a type:

crate struct ExplicitPredicatesMap<'tcx> {
  map: FxHashMap<DefId, RequiredPredicates<'tcx>>
}

The map would publish one method:

impl ExplicitPredicatesMap<'tcx> {
    crate fn explicit_predicates_of(&mut self, tcx: TyCtxt<'_, '_, 'tcx>, def_id: DefId) -> &RequiredPredicates<'tcx> {
        self.map.entry(def_id).or_insert_with(|| {
            let predicates = if def_id.is_local() {
                tcx.explicit_predicates_of(def_id)
            } else {
                tcx.predicates_of(def_id)
            };
            let required_predicates = {
                // process predicates and convert to `RequiredPredicates` entry, see below
            };
            required_predicates
        }
    }
}

The "processing comment" would basically be doing the same as this existing code, which filters down Predicate<'tcx> values to a RequiredPredicate<'tcx>:

for pred in local_explicit_predicate.into_iter() {
match pred {
ty::Predicate::TypeOutlives(predicate) => {
let ty::OutlivesPredicate(ref ty, ref reg) = predicate.skip_binder();
insert_outlives_predicate(self.tcx, (*ty).into(), reg, &mut required_predicates)
}
ty::Predicate::RegionOutlives(predicate) => {
let ty::OutlivesPredicate(ref reg1, ref reg2) = predicate.skip_binder();
insert_outlives_predicate(
self.tcx,
(*reg1).into(),
reg2,
&mut required_predicates,
)
}
ty::Predicate::Trait(..)
| ty::Predicate::Projection(..)
| ty::Predicate::WellFormed(..)
| ty::Predicate::ObjectSafe(..)
| ty::Predicate::ClosureKind(..)
| ty::Predicate::Subtype(..)
| ty::Predicate::ConstEvaluatable(..) => (),
}
}

@nikomatsakis nikomatsakis added the E-mentor Call for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion. label Jun 28, 2018
@nrc nrc added A-edition-2018-lints F-rust_2018_preview `#![feature(rust_2018_preview)]` and removed A-edition-2018-lints labels Jul 2, 2018
@jkordish jkordish added the C-enhancement Category: An issue proposing an enhancement or a PR with one. label Jul 3, 2018
bors added a commit that referenced this issue Jul 6, 2018
Fix: infer outlives requirements across crates

Fixes #51858
@fmease fmease added the A-edition-2018 Area: The 2018 edition label Dec 21, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-edition-2018 Area: The 2018 edition C-enhancement Category: An issue proposing an enhancement or a PR with one. E-mentor Call for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion. F-rust_2018_preview `#![feature(rust_2018_preview)]` T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

5 participants