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

WIP: Check uninhabitedness through the trait solver #116247

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

cjgillot
Copy link
Contributor

The current implementation with the type InhabitednessPredicate does not handle well normalization and aliases. This PR proposes to compute uninhabitedness using the trait solver. This allows to handle those seamlessly. This also opens way for a future potential extension to uninhabitedness to coinductive cycles (references to uninhabited for instance).

This implementation is still WIP and clumsy. The logic is duplicated 3 times (once the new solver, twice the old solver). I'm not sure how to reduce that. I'm also very probably using functions that are not compatible with the solvers. It may lack a cycle check somewhere in the old solver.

This also needs a few extra tests.

r? @lcnr

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. WG-trait-system-refactor The Rustc Trait System Refactor Initiative (-Znext-solver) labels Sep 28, 2023
@rust-log-analyzer

This comment has been minimized.

Copy link
Member

@compiler-errors compiler-errors left a comment

Choose a reason for hiding this comment

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

Some initial comments. Very interesting idea, though. I like the premise, but it does make me a bit nervous about its interaction with the old trait solver.

(Side-note, I hope you can appreciate how much simpler the new trait solver is 💞)

},
ty::Alias(ty::Opaque, _) => Err(NoSolution),
// FIXME
ty::Alias(ty::Projection | ty::Inherent, _) => Err(NoSolution),
Copy link
Member

Choose a reason for hiding this comment

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

We never encounter ty::Inherent unless it's not well-formed.

Copy link
Member

Choose a reason for hiding this comment

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

The only case we'd encounter ty::Projection if it's "rigid", like T::Item in fn<T: Iterator>() {}. In that case, yeah, we don't know how to tell that it's uninhabited.

self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
}
},
ty::Alias(ty::Opaque, _) => Err(NoSolution),
Copy link
Member

Choose a reason for hiding this comment

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

Needs a comment saying that we don't look into the hidden type of the opaque, and it would've been revealed above.

return self.evaluate_added_goals_and_make_canonical_response(Certainty::OVERFLOW);
};
match ty.kind() {
ty::Never => self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes),
Copy link
Member

Choose a reason for hiding this comment

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

Needs to return ambiguity on ty::Infer(ty::TyVar(_)) -- should also ICE on fresh tys, etc.

@@ -141,7 +141,7 @@ pub fn type_known_to_meet_bound_modulo_regions<'tcx>(
/// Ping me on zulip if you want to use this method and need help with finding
/// an appropriate replacement.
#[instrument(level = "debug", skip(infcx, param_env, pred), ret)]
fn pred_known_to_hold_modulo_regions<'tcx>(
pub fn pred_known_to_hold_modulo_regions<'tcx>(
Copy link
Member

Choose a reason for hiding this comment

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

I'd expose a type_known_to_be_uninhabited_modulo_regions instead of exposing this fn fully

let tcx = infcx.tcx;
for ty in tys {
let response = infcx.probe(|_| {
self.evaluate_predicates_recursively(
Copy link
Member

Choose a reason for hiding this comment

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

Yeah, we don't do any cycle detection with these uninhabited predicates :s

}
}
});
match self.evaluate_uninhabited_predicate_fields(previous_stack, obligation, module, field_tys)? {
Copy link
Member

Choose a reason for hiding this comment

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

We're not normalizing these field tys, are we? Does the old uninhabitedness check consider normalization?

@@ -33,6 +34,26 @@ fn is_item_raw<'tcx>(
traits::type_known_to_meet_bound_modulo_regions(&infcx, param_env, ty, trait_def_id)
}

fn type_is_uninhabited_from_raw<'tcx>(
Copy link
Member

Choose a reason for hiding this comment

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

Since we're already caching this for non-infer tys, do we need to do caching in the (old) trait solver as well?

ty::Alias(ty::Projection | ty::Inherent, _) => Err(NoSolution),
// use a query for more complex cases
// references and other types are inhabited
_ => Err(NoSolution),
Copy link
Member

Choose a reason for hiding this comment

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

Can you make this exhaustive just for good measure? We prefer exhaustive matches on TyKind in the new solver "just in case" 😸

.ok()
})
.collect();
self.try_merge_responses(&responses).ok_or(NoSolution)
Copy link
Contributor

Choose a reason for hiding this comment

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

need to flounder if that returns None, we also return None if there are are multiple candidates which cannot be merged. In this case we want to return ambiguity instead of NoSolution

@bors
Copy link
Contributor

bors commented Oct 3, 2023

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

@Dylan-DPC Dylan-DPC added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Feb 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. WG-trait-system-refactor The Rustc Trait System Refactor Initiative (-Znext-solver)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants