mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-29 23:04:49 +00:00
prevent a subs lookup by reserving a Variable
This commit is contained in:
parent
cc5c734c20
commit
41e56519ef
2 changed files with 16 additions and 14 deletions
|
@ -1928,7 +1928,8 @@ fn deep_copy_var_help(
|
||||||
use roc_types::subs::Content::*;
|
use roc_types::subs::Content::*;
|
||||||
use roc_types::subs::FlatType::*;
|
use roc_types::subs::FlatType::*;
|
||||||
|
|
||||||
let desc = subs.get_without_compacting(var);
|
let subs_len = subs.len();
|
||||||
|
let desc = subs.get_ref_mut(var);
|
||||||
|
|
||||||
if let Some(copy) = desc.copy.into_variable() {
|
if let Some(copy) = desc.copy.into_variable() {
|
||||||
return copy;
|
return copy;
|
||||||
|
@ -1945,8 +1946,13 @@ fn deep_copy_var_help(
|
||||||
copy: OptVariable::NONE,
|
copy: OptVariable::NONE,
|
||||||
};
|
};
|
||||||
|
|
||||||
let content = desc.content;
|
let content = desc.content.clone();
|
||||||
let copy = subs.fresh(make_descriptor(content.clone()));
|
|
||||||
|
// Safety: Here we make a variable that is 1 position out of bounds.
|
||||||
|
// The reason is that we can now keep the mutable reference to `desc`
|
||||||
|
// Below, we actually push a new variable onto subs meaning the `copy`
|
||||||
|
// variable is in-bounds before it is ever used.
|
||||||
|
let copy = unsafe { Variable::from_index(subs_len as u32) };
|
||||||
|
|
||||||
pools.get_mut(max_rank).push(copy);
|
pools.get_mut(max_rank).push(copy);
|
||||||
|
|
||||||
|
@ -1954,15 +1960,11 @@ fn deep_copy_var_help(
|
||||||
// avoid making multiple copies of the variable we are instantiating.
|
// avoid making multiple copies of the variable we are instantiating.
|
||||||
//
|
//
|
||||||
// Need to do this before recursively copying to avoid looping.
|
// Need to do this before recursively copying to avoid looping.
|
||||||
subs.set(
|
desc.mark = Mark::NONE;
|
||||||
var,
|
desc.copy = copy.into();
|
||||||
Descriptor {
|
|
||||||
content: content.clone(),
|
let actual_copy = subs.fresh(make_descriptor(content.clone()));
|
||||||
rank: desc.rank,
|
debug_assert_eq!(copy, actual_copy);
|
||||||
mark: Mark::NONE,
|
|
||||||
copy: copy.into(),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
// Now we recursively copy the content of the variable.
|
// Now we recursively copy the content of the variable.
|
||||||
// We have already marked the variable as copied, so we
|
// We have already marked the variable as copied, so we
|
||||||
|
|
|
@ -736,8 +736,8 @@ impl Variable {
|
||||||
|
|
||||||
/// # Safety
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// This should only ever be called from tests!
|
/// It is not guaranteed that the variable is in bounds.
|
||||||
pub unsafe fn unsafe_test_debug_variable(v: u32) -> Self {
|
pub unsafe fn from_index(v: u32) -> Self {
|
||||||
debug_assert!(v >= Self::NUM_RESERVED_VARS as u32);
|
debug_assert!(v >= Self::NUM_RESERVED_VARS as u32);
|
||||||
Variable(v)
|
Variable(v)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue