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

Remove Ord from chalk_ir::interner::DefId #740

Merged
merged 1 commit into from
Dec 23, 2021
Merged

Conversation

pierwill
Copy link
Member

@pierwill pierwill commented Dec 17, 2021

This change is required for rust-lang/rust#90749.

For background on the initiative of removing ordering traits from items like DefId in rustc, see rust-lang/rust#90317.

@pierwill pierwill changed the title [WIP] Remove Ord from chalk_ir::interner::DefId (second attempt) Remove Ord from chalk_ir::interner::DefId Dec 17, 2021
@pierwill
Copy link
Member Author

pierwill commented Dec 17, 2021

@rustbot assign @jackh726 cc @nikomatsakis

@jackh726
Copy link
Member

Interesting...I forgot that auto traits are sorted in chalk-integration, where the DefId is Ord. I can't think of any other place that needs Ord..

@pierwill

This comment has been minimized.

@rustbot
Copy link
Collaborator

rustbot commented Dec 22, 2021

Error: The feature relabel is not enabled in this repository.
To enable it add its section in the triagebot.toml in the root of the repository.

Please let @rust-lang/release know if you're having trouble with this bot.

chalk-solve/src/coherence.rs Outdated Show resolved Hide resolved
chalk-solve/src/coherence.rs Outdated Show resolved Hide resolved

// Find all specializations (implemented in coherence/solve)
// Record them in the forest by adding an edge from the less special
// to the more special.
self.visit_specializations_of_trait(|less_special, more_special| {
forest.add_edge(less_special, more_special, ());
// Check so that we never add multiple nodes with the same ImplId.
let l = forest.add_node(less_special);
Copy link
Member

Choose a reason for hiding this comment

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

If we didn't add the nodes before, why do we need to add them now? update_edge doesn't do anything different versus add_edge with respect to nodes.

Copy link
Member Author

@pierwill pierwill Dec 22, 2021

Choose a reason for hiding this comment

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

The nodes must be added because petgraph::graphmap::GraphMap::add_edge can take a generic type N (that must implement Ord), where petgraph::graph::Graph::update_edge takes a NodeIndex.

We need to use Graph since this PR removes Ord from ImplId.

Copy link
Member

Choose a reason for hiding this comment

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

Ah, I was looking at Graph::add_edge.

Can this create duplicate nodes?

Copy link
Member Author

@pierwill pierwill Dec 23, 2021

Choose a reason for hiding this comment

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

petgraph::graph::Graph::add_node does create multiple nodes when given the same value. (Playground example.)

Copy link
Member Author

Choose a reason for hiding this comment

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

I'm going to see if I can handle this logic with a match statement:

let node_impls: Vec<ImplId<_>> = forest.raw_nodes().iter().map(|x| x.weight).collect();
self.visit_specializations_of_trait(|less_special, more_special| {
    match (
        node_impls.contains(&less_special),
        node_impls.contains(&more_special),
    ) {
        (true, true) => todo!(),
        (true, false) => todo!(),
        (false, true) => todo!(),
        (false, false) => todo!(),
    }
}

Copy link
Member

Choose a reason for hiding this comment

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

I see "Add or update an edge from a to b." - So it's basically add_edge without allowing duplicates.

Copy link
Member

Choose a reason for hiding this comment

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

Seems like it might make sense to keep around a Map<ImplId, NodeIndex>

Copy link
Member

Choose a reason for hiding this comment

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

Before visit_specialization_of_trait, forest will be empty...

Copy link
Member Author

@pierwill pierwill Dec 23, 2021

Choose a reason for hiding this comment

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

I'm trying to reason this out. The logic below seems right, but I'm not sure how to get the indices for existing nodes...

// Find all specializations. (This is implemented in coherence/solve.)
// Record them in the forest by adding an edge from the less special
// to the more special.
self.visit_specializations_of_trait(|less_special, more_special| {
    match (
        node_impls.contains(&less_special),
        node_impls.contains(&more_special),
    ) {
        (true, true) => {
            // but how do we get indices for l and m?
            forest.add_edge(l, m, ());
        }
        (true, false) => {
            let m = forest.add_node(more_special);
            // but how do we get index for l?
            forest.add_edge(l, m, ());
        }
        (false, true) => {
            let l = forest.add_node(less_special);
            // but how do we get index for m?
            forest.add_edge(l, m, ());
        }
        (false, false) => {
            // add L and M
            let l = forest.add_node(less_special);
            let m = forest.add_node(more_special);
            forest.add_edge(l, m, ());
        }
    }
})?;

Can this even be done correctly without GraphMap? 😬

Update: Ah. node_indices might work...

Copy link
Member

Choose a reason for hiding this comment

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

I'm thinking something like

let mut forest = DiGraph::new();
let mut node_map = FxHashMap::new();
self.visit_specializations_of_trait(|less_special, more_special| {
    let less_special_node = *node_map.entry(less_special).or_insert_with(|| forest.add_node(less_special));
    let more_special_node = *node_map.entry(more_special).or_insert_with(|| forest.add_node(more_special));
    forest.update_edge(less_special_noe, more_special_node, ());
}

Copy link
Member

@jackh726 jackh726 left a comment

Choose a reason for hiding this comment

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

Nits but LGTM otherwise

chalk-solve/src/display/state.rs Show resolved Hide resolved
chalk-solve/src/display/state.rs Outdated Show resolved Hide resolved
chalk-solve/src/coherence.rs Outdated Show resolved Hide resolved
Use `indexmap` to obviate need for ordering `DefId`s.

In specialization forest, use a map of ImplIds to node indices
to avoid duplicate nodes.
@jackh726
Copy link
Member

@bors r+

@bors
Copy link
Collaborator

bors commented Dec 23, 2021

📌 Commit 29c1d17 has been approved by jackh726

@bors
Copy link
Collaborator

bors commented Dec 23, 2021

⌛ Testing commit 29c1d17 with merge f518c7c...

@bors
Copy link
Collaborator

bors commented Dec 23, 2021

☀️ Test successful - checks-actions
Approved by: jackh726
Pushing f518c7c to master...

@bors bors merged commit f518c7c into rust-lang:master Dec 23, 2021
@pierwill pierwill deleted the rm2 branch December 23, 2021 18:15
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Jan 20, 2022
⬆ chalk to 0.76.0

This update contains rust-lang/chalk#740, which is needed for work on rust-lang#90317.
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.

4 participants