Estou lendo "o livro" e queria testar minha compreensão das regras de empréstimo no fatiamento de capítulos .
Fiquei impressionado com (minha suposição de) como o verificador de empréstimos associava o que eu passava, com o que a função retornava. Então, tentei alguns exemplos para testar meu entendimento, e estou com dificuldades para descobrir as regras do verificador de empréstimos.
- Por que
test1
falha ao compilar, ondetest5
funciona? - Onde meu entendimento está quebrado? (veja o processo de pensamento abaixo)
- Onde "o livro" aborda o que estou perdendo?
Este código é sempre o mesmo:
fn tmp() {
let mut s = String::from("hello world");
let thing = testX(&s);
s.clear(); // error!
let tmp = thing.len();
println!("the first word is: {tmp}");
}
Teste 1:
fn test1(s: &String) -> &str {
"Slice"
}
Aqui estou passando uma referência imutável de uma string mutável, mas não a uso na função. Eu retorno uma fatia diferente (na minha mente, uma string imutável diferente). Acredito que uma vez test1
retornado ele não mantém mais seu empréstimo em &s
. Eu esperava que esse código compilasse, mas não compila, eu ainda mantenho de alguma forma um empréstimo imutável em s
.
Então eu me perguntei se o verificador de empréstimo correlaciona o tipo retornado com o tipo que foi passado.
Teste 2:
fn test2(s: &String) -> Vec<&str> {
let mut vec = Vec::new();
vec.push(s.as_str());
vec
}
Tentei ser criativo com mais indireção. Não tenho ideia do que as_str()
acontece em termos de propriedade, mas estou interessado em aprender. Aqui estou passando de volta uma parte do que foi passado, então não estou surpreso que não compile, mas já suspeito que meu entendimento das regras esteja errado.
Teste 3
fn test3(s: &String) -> Vec<&str> {
let mut vec = Vec::new();
vec.push("Slice");
vec
}
Eu sigo um raciocínio similar ao test1
, também não compila. Isso me diz que não se trata de retornar um tipo de referência do tipo que foi passado, a menos que esteja estendendo o raciocínio para o tipo do vetor proprietário..?
Teste 4
fn test4(s: &String) -> Vec<&usize> {
let mut vec = Vec::new();
vec.push(&1);
vec
}
Agora estou ficando furtivo, estou criando um código que acho que é comparável a test3
, mas retorna um tipo não relacionado. Ainda assim, o compilador não permite. Então parece que por algum motivo a função está segurando o empréstimo de &String
depois que ele retorna?!
Teste 5
fn test5(s: &String) -> Vec<String> {
let mut vec = Vec::new();
vec.push(String::from("something new"));
vec
}
Eu tentei isso, esperando que também não compilasse, mas funcionou!
Eu vejo isso como logicamente o mesmo que test1
em relação ao empréstimo de s
. Em ambos os casos, não estou fazendo nada com s
, mas ainda assim test1
mantenho o empréstimo, enquanto test5
não.
Ajuda!