< 返回版块

freewong 发表于 2023-11-21 21:25

fn foo(x:&str,y:&str) ->&str{
    "hello"
}

上面这段代码无法编译,提示是 返回值需要显式标注生命周期。

根据生命周期省略规则,两个输入的参数分别会赋于两个不同的生命周期,这里设为'a,'b 同时,根据规则,函数在这样的情况返回值的生命周期必须是'a或是'b中的一个。

好,问题来了,我就是想返回一个毫无逻辑的 "hello",它和两个输入参数根本无关,这样也不让我编译通过是不是有点怪怪的?

评论区

写评论
wukong 2023-11-24 10:56

楼主说的其实是对的,能做到就好了。可是考虑到现实情况,Rust 现在就是看函数签名。想想下面的程序:

fn bar(){
    let x = "hello";
    let y = "world";
    foo(x, y);
}

Rust 在分析 bar 函数内容时,只会看 foo 的签名。

全称量词 2023-11-24 00:38

你可以说你返回引用的生命周期不和传入参数相关,哪又能和谁相关?和函数本身的生命周期相关吗?函数本身调用过后生命周期就没了,但是你在函数里创建的引用不能被销毁,否则这个引用就变成悬垂引用了。

把返回引用和某个参数的生命周期关联,编译器就知道返回引用的生命周期了:和被关联参数的生命周期保持一致。

编译器不会知道和哪个关联,因为如果两个传入的引用的生命周期不一致的话,编译器无法代替程序员作出选择。更何况你举的例子中返回的引用不与传入参数有任何的关系,也就没有任何的信息做分析。

学的不好,都是一些低见。rust 是开源的,如果你有解决方案,可以拉请求。

ribs 2023-11-22 12:04

不是没考虑到,而是完全不需要考虑到,生命周期标注是必须的,但就像@chirsz-ever说的, 为了改善编程体验,Rust 允许省略常见情况的生命周期标注,重点是“常见情况”。

作者 freewong 2023-11-22 11:37

编译器就是编译器,它无需也无法关注使用者的业务逻辑,即使它毫无逻辑,如果你看我不使用传入的参数不爽,那我给你看一下使用传入参数的

fn bar(x:&str,y:&str) -> &i32{
  if x==""{
    &0
  }else{
    &1
  }
}

这个也无法编译,愿闻你的高论

bbjia 2023-11-22 10:38

典型闲的蛋疼

作者 freewong 2023-11-22 10:12

这个不是我发布的,应该是由 @Shylock-Hg 少侠发布的

--
👇
苦瓜小仔: 你发布的交叉贴 https://users.rust-lang.org/t/a-unnecessary-lifetime-mark/102855

chirsz-ever 2023-11-22 00:33

Rust 认为函数的实现不能影响函数签名,不然容易产生改了函数里的实现代码导致调用函数的地方编译错误的事。

为了改善编程体验,Rust 允许省略常见情况的生命周期标注,比如签名为 fn(&T)->&U 的函数实际是 fn<'a>(&'a T) -> &'a U 的省略。

一个例子:

struct A(String);

fn foo(x: &A) -> &str {
    "foo"
}

fn main() {
    let x = A(String::from("aaa"));
    let y = foo(&x);
    drop(x);
    dbg!(y);
}

这段代码会报生命周期错误,尽管实际上没有生命周期问题。因为这里 foo 的签名按照省略规则被推断为 fn<'a>(x: &'a A) -> &'a str,rustc 作生命周期检查时只看函数签名,结果报错。

foo 的返回类型改为 &'static str 就没有问题了。

c5soft 2023-11-21 22:11

这个问题是问题吗?返回结果与传入参数无关,要传入参数干嘛? 如果非要这样干,多敲几下键盘有啥关系?非要编译器增加这个无聊的功能吗?

如果非要这样一个函数,有两种写法:

fn foo(x: &str, y: &str) -> &'static str {
    "hello"
}

fn foo2<'c>(x: &str, y: &str) -> &'c str {
    "world"
}

fn main() {
    let a = foo("x", "y");
    let b = foo2("x", "y");
    println!("{} {}", a,b);
}

苦瓜小仔 2023-11-21 22:10

不满足省略规则的语法糖,都要自己指定函数上的生命周期关系。

别指望 Rust 会通过分析函数体内的生命周期来“智能”标注 —— 稳定的、显式的生命周期标注是 API 可靠性的基本保证。

作者 freewong 2023-11-21 21:42

根据规则是这样,但我这个明显就属于他们没有考虑到的情况了

--
👇
Shylock-Hg: rustc这里默认你的输出是依赖所有输入参数的。

作者 freewong 2023-11-21 21:41

或许是编译器的规则没有想到这个

--
👇
Shylock-Hg: 应该是rustc分析生命周期的时候只看了函数签名,不会分析输入输出实际的变换情况。

Shylock-Hg 2023-11-21 21:39

rustc这里默认你的输出是依赖所有输入参数的。

Shylock-Hg 2023-11-21 21:29

应该是rustc分析生命周期的时候只看了函数签名,不会分析输入输出实际的变换情况。

1 共 14 条评论, 1 页