6222: Fix stackoverflow in insert_use::recursive_merge r=matklad a=Veykril

Fixes #6221.

#6108 shouldn't be related to this as autocompletion doesn't depend on this code.

Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
This commit is contained in:
bors[bot] 2020-10-14 10:15:51 +00:00 committed by GitHub
commit 69f1c8aa6e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 53 additions and 2 deletions

View file

@ -72,6 +72,20 @@ mod tests {
use super::*;
#[test]
fn test_merge_equal() {
check_assist(
merge_imports,
r"
use std::fmt<|>::{Display, Debug};
use std::fmt::{Display, Debug};
",
r"
use std::fmt::{Debug, Display};
",
)
}
#[test]
fn test_merge_first() {
check_assist(

View file

@ -123,6 +123,23 @@ mod tests {
use super::*;
#[test]
fn test_replace_already_imported() {
check_assist(
replace_qualified_name_with_use,
r"use std::fs;
fn main() {
std::f<|>s::Path
}",
r"use std::fs;
fn main() {
fs::Path
}",
)
}
#[test]
fn test_replace_add_use_no_anchor() {
check_assist(

View file

@ -173,8 +173,15 @@ pub(crate) fn try_merge_trees(
let rhs_path = rhs.path()?;
let (lhs_prefix, rhs_prefix) = common_prefix(&lhs_path, &rhs_path)?;
let lhs = lhs.split_prefix(&lhs_prefix);
let rhs = rhs.split_prefix(&rhs_prefix);
let (lhs, rhs) = if is_simple_path(lhs)
&& is_simple_path(rhs)
&& lhs_path == lhs_prefix
&& rhs_path == rhs_prefix
{
(lhs.clone(), rhs.clone())
} else {
(lhs.split_prefix(&lhs_prefix), rhs.split_prefix(&rhs_prefix))
};
recursive_merge(&lhs, &rhs, merge)
}
@ -250,6 +257,10 @@ fn recursive_merge(
use_trees.insert(idx, make::glob_use_tree());
continue;
}
if lhs_t.use_tree_list().is_none() && rhs_t.use_tree_list().is_none() {
continue;
}
}
let lhs = lhs_t.split_prefix(&lhs_prefix);
let rhs = rhs_t.split_prefix(&rhs_prefix);
@ -295,6 +306,10 @@ fn common_prefix(lhs: &ast::Path, rhs: &ast::Path) -> Option<(ast::Path, ast::Pa
}
}
fn is_simple_path(use_tree: &ast::UseTree) -> bool {
use_tree.use_tree_list().is_none() && use_tree.star_token().is_none()
}
fn path_is_self(path: &ast::Path) -> bool {
path.segment().and_then(|seg| seg.self_token()).is_some() && path.qualifier().is_none()
}
@ -523,6 +538,11 @@ mod tests {
use test_utils::assert_eq_text;
#[test]
fn insert_existing() {
check_full("std::fs", "use std::fs;", "use std::fs;")
}
#[test]
fn insert_start() {
check_none(