-
Notifications
You must be signed in to change notification settings - Fork 173
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
Fix modules with same name as builtins causing ICE (#3315) #3437
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -34,6 +34,13 @@ ForeverStack<N>::Node::is_root () const | |
return !parent.has_value (); | ||
} | ||
|
||
template <Namespace N> | ||
bool | ||
ForeverStack<N>::Node::is_prelude () const | ||
{ | ||
return rib.kind == Rib::Kind::Prelude; | ||
} | ||
|
||
template <Namespace N> | ||
bool | ||
ForeverStack<N>::Node::is_leaf () const | ||
|
@@ -63,6 +70,16 @@ template <Namespace N> | |
void | ||
ForeverStack<N>::push_inner (Rib rib, Link link) | ||
{ | ||
if (rib.kind == Rib::Kind::Prelude) | ||
{ | ||
// If you push_inner into the prelude from outside the root, you will pop | ||
// back into the root, which could screw up a traversal. | ||
rust_assert (&cursor_reference.get () == &root); | ||
// Prelude doesn't have an access path | ||
rust_assert (!link.path); | ||
update_cursor (this->prelude); | ||
return; | ||
} | ||
// If the link does not exist, we create it and emplace a new `Node` with the | ||
// current node as its parent. `unordered_map::emplace` returns a pair with | ||
// the iterator and a boolean. If the value already exists, the iterator | ||
|
@@ -290,6 +307,20 @@ ForeverStack<N>::get (const Identifier &name) | |
return resolved_definition; | ||
} | ||
|
||
template <Namespace N> | ||
tl::optional<Rib::Definition> | ||
ForeverStack<N>::get_prelude (const Identifier &name) | ||
{ | ||
return prelude.rib.get (name.as_string ()); | ||
} | ||
|
||
template <Namespace N> | ||
tl::optional<Rib::Definition> | ||
ForeverStack<N>::get_prelude (const std::string &name) | ||
{ | ||
return prelude.rib.get (name); | ||
} | ||
|
||
template <> | ||
tl::optional<Rib::Definition> inline ForeverStack<Namespace::Labels>::get ( | ||
const Identifier &name) | ||
|
@@ -389,7 +420,7 @@ ForeverStack<N>::find_starting_point ( | |
break; | ||
|
||
auto &seg = unwrap_type_segment (outer_seg); | ||
auto is_self_or_crate | ||
bool is_self_or_crate | ||
= seg.is_crate_path_seg () || seg.is_lower_self_seg (); | ||
|
||
// if we're after the first path segment and meet `self` or `crate`, it's | ||
|
@@ -452,7 +483,7 @@ ForeverStack<N>::resolve_segments ( | |
typename std::vector<S>::const_iterator iterator, | ||
std::function<void (const S &, NodeId)> insert_segment_resolution) | ||
{ | ||
auto *current_node = &starting_point; | ||
Node *current_node = &starting_point; | ||
for (; !is_last (iterator, segments); iterator++) | ||
{ | ||
auto &outer_seg = *iterator; | ||
|
@@ -468,7 +499,7 @@ ForeverStack<N>::resolve_segments ( | |
} | ||
|
||
auto &seg = unwrap_type_segment (outer_seg); | ||
auto str = seg.as_string (); | ||
std::string str = seg.as_string (); | ||
rust_debug ("[ARTHUR]: resolving segment part: %s", str.c_str ()); | ||
|
||
// check that we don't encounter *any* leading keywords afterwards | ||
|
@@ -483,10 +514,20 @@ ForeverStack<N>::resolve_segments ( | |
* On every iteration this loop either | ||
* | ||
* 1. terminates | ||
* 2. decreases the depth of the node pointed to by current_node | ||
* | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should probably add an entry to the numbered list in the above comment, mentioning changing There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I added a comment for this, let me know if it needs modification. |
||
* This ensures termination | ||
* 2. decreases the depth of the node pointed to by current_node until | ||
* current_node reaches the root | ||
* | ||
* 3. If the root node is reached, and we were not able to resolve the | ||
* segment, we search the prelude rib for the segment, by setting | ||
* current_node to point to the prelude, and toggling the | ||
* searched_prelude boolean to true. If current_node is the prelude | ||
* rib, and searched_prelude is true, we will exit. | ||
* | ||
* This ensures termination. | ||
* | ||
*/ | ||
bool searched_prelude = false; | ||
while (true) | ||
{ | ||
// may set the value of child | ||
|
@@ -522,9 +563,16 @@ ForeverStack<N>::resolve_segments ( | |
} | ||
} | ||
|
||
if (current_node->is_root () && !searched_prelude) | ||
{ | ||
searched_prelude = true; | ||
current_node = &prelude; | ||
continue; | ||
} | ||
|
||
if (!is_start (iterator, segments) | ||
|| current_node->rib.kind == Rib::Kind::Module | ||
|| current_node->is_root ()) | ||
|| current_node->is_prelude ()) | ||
{ | ||
return tl::nullopt; | ||
} | ||
|
@@ -564,7 +612,12 @@ ForeverStack<N>::resolve_path ( | |
return Rib::Definition::NonShadowable (seg_id); | ||
} | ||
|
||
auto res = get (unwrap_type_segment (segments.back ()).as_string ()); | ||
tl::optional<Rib::Definition> res | ||
= get (unwrap_type_segment (segments.back ()).as_string ()); | ||
|
||
if (!res) | ||
res = get_prelude (unwrap_type_segment (segments.back ()).as_string ()); | ||
|
||
if (res && !res->is_ambiguous ()) | ||
insert_segment_resolution (segments.back (), res->get_node_id ()); | ||
return res; | ||
|
@@ -579,16 +632,25 @@ ForeverStack<N>::resolve_path ( | |
return resolve_segments (starting_point.get (), segments, iterator, | ||
insert_segment_resolution); | ||
}) | ||
.and_then ([&segments, &insert_segment_resolution] ( | ||
.and_then ([this, &segments, &insert_segment_resolution] ( | ||
Node final_node) -> tl::optional<Rib::Definition> { | ||
// leave resolution within impl blocks to type checker | ||
if (final_node.rib.kind == Rib::Kind::TraitOrImpl) | ||
return tl::nullopt; | ||
|
||
std::string seg_name | ||
= unwrap_type_segment (segments.back ()).as_string (); | ||
|
||
// assuming this can't be a lang item segment | ||
auto res = final_node.rib.get ( | ||
unwrap_type_segment (segments.back ()).as_string ()); | ||
tl::optional<Rib::Definition> res = final_node.rib.get (seg_name); | ||
|
||
// Ok we didn't find it in the rib, Lets try the prelude... | ||
if (!res) | ||
res = get_prelude (seg_name); | ||
|
||
if (res && !res->is_ambiguous ()) | ||
insert_segment_resolution (segments.back (), res->get_node_id ()); | ||
|
||
return res; | ||
}); | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
//You should be able to create a module of the same name as a builtin type | ||
|
||
mod i32 { | ||
} | ||
|
||
fn main() -> isize { | ||
0 | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
mod i32 { | ||
} | ||
|
||
fn main() -> isize { | ||
let i:i32 = 0 as i32; | ||
i as isize | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I probably should have noticed and commented on this earlier, but this should really be called something like
language_prelude
, given that we'll have to deal with multiple preludesThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I considered that as well, I figured that we would also dump the std::prelude and core::prelude in here as well
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I figured we'd keep some sort of reference to the standard library prelude -- since that should already be a module with its own
Node
, we shouldn't need to try to copy entries into anotherNode
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the comment there clarifies that it's currently only used for the language prelude (language builtins). If it needs to be beefed up with a better explanation I can do that.