Skip to content

Commit

Permalink
Stop skewing inference in ?'s desugaring
Browse files Browse the repository at this point in the history
  • Loading branch information
WaffleLapkin committed Apr 3, 2024
1 parent 92130a3 commit b478d2b
Show file tree
Hide file tree
Showing 22 changed files with 80 additions and 63 deletions.
30 changes: 22 additions & 8 deletions compiler/rustc_ast_lowering/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1758,9 +1758,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
/// ControlFlow::Break(residual) =>
/// #[allow(unreachable_code)]
/// // If there is an enclosing `try {...}`:
/// break 'catch_target Try::from_residual(residual),
/// absurd(break 'catch_target Try::from_residual(residual)),
/// // Otherwise:
/// return Try::from_residual(residual),
/// absurd(return Try::from_residual(residual)),
/// }
/// ```
fn lower_expr_try(&mut self, span: Span, sub_expr: &Expr) -> hir::ExprKind<'hir> {
Expand All @@ -1769,6 +1769,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
span,
Some(self.allow_try_trait.clone()),
);

let absurd_allowed_span = self.mark_span_with_reason(
DesugaringKind::QuestionMark,
span,
Some(self.allow_convert_absurd.clone()),
);

let try_span = self.tcx.sess.source_map().end_point(span);
let try_span = self.mark_span_with_reason(
DesugaringKind::QuestionMark,
Expand Down Expand Up @@ -1810,7 +1817,7 @@ impl<'hir> LoweringContext<'_, 'hir> {

// `ControlFlow::Break(residual) =>
// #[allow(unreachable_code)]
// return Try::from_residual(residual),`
// absurd(return Try::from_residual(residual)),`
let break_arm = {
let residual_ident = Ident::with_dummy_span(sym::residual);
let (residual_local, residual_local_nid) = self.pat_ident(try_span, residual_ident);
Expand All @@ -1823,20 +1830,27 @@ impl<'hir> LoweringContext<'_, 'hir> {
);
let ret_expr = if let Some(catch_node) = self.catch_scope {
let target_id = Ok(self.lower_node_id(catch_node));
self.arena.alloc(self.expr(
self.expr(
try_span,
hir::ExprKind::Break(
hir::Destination { label: None, target_id },
Some(from_residual_expr),
),
))
)
} else {
self.arena.alloc(self.expr(try_span, hir::ExprKind::Ret(Some(from_residual_expr))))
self.expr(try_span, hir::ExprKind::Ret(Some(from_residual_expr)))
};
self.lower_attrs(ret_expr.hir_id, &attrs);

let absurd_expr = self.expr_call_lang_item_fn(
absurd_allowed_span,
hir::LangItem::Absurd,
arena_vec![self; ret_expr],
);

self.lower_attrs(absurd_expr.hir_id, &attrs);

let break_pat = self.pat_cf_break(try_span, residual_local);
self.arm(break_pat, ret_expr)
self.arm(break_pat, absurd_expr)
};

hir::ExprKind::Match(
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ struct LoweringContext<'a, 'hir> {
node_id_to_local_id: NodeMap<hir::ItemLocalId>,

allow_try_trait: Lrc<[Symbol]>,
allow_convert_absurd: Lrc<[Symbol]>,
allow_gen_future: Lrc<[Symbol]>,
allow_async_iterator: Lrc<[Symbol]>,
allow_for_await: Lrc<[Symbol]>,
Expand Down Expand Up @@ -173,6 +174,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
impl_trait_defs: Vec::new(),
impl_trait_bounds: Vec::new(),
allow_try_trait: [sym::try_trait_v2, sym::yeet_desugar_details].into(),
allow_convert_absurd: [sym::convert_absurd].into(),
allow_gen_future: if tcx.features().async_fn_track_caller {
[sym::gen_future, sym::closure_track_caller].into()
} else {
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -602,6 +602,7 @@ symbols! {
const_try,
constant,
constructor,
convert_absurd,
convert_identity,
copy,
copy_closures,
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/async-await/issue-67765-async-diagnostic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ async fn func<'a>() -> Result<(), &'a str> {

let b = &s[..];

Err(b)?; //~ ERROR cannot return value referencing local variable `s`
Err::<(), _>(b)?; //~ ERROR cannot return value referencing local variable `s`

Ok(())
}
4 changes: 2 additions & 2 deletions tests/ui/async-await/issue-67765-async-diagnostic.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ error[E0515]: cannot return value referencing local variable `s`
LL | let b = &s[..];
| - `s` is borrowed here
LL |
LL | Err(b)?;
| ^^^^^^^ returns a value referencing data owned by the current function
LL | Err::<(), _>(b)?;
| ^^^^^^^^^^^^^^^^ returns a value referencing data owned by the current function

error: aborting due to 1 previous error

Expand Down
4 changes: 2 additions & 2 deletions tests/ui/consts/try-operator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@

fn main() {
const fn result() -> Result<bool, ()> {
Err(())?;
Err::<(), _>(())?;
Ok(true)
}

const FOO: Result<bool, ()> = result();
assert_eq!(Err(()), FOO);

const fn option() -> Option<()> {
None?;
None::<()>?;
Some(())
}
const BAR: Option<()> = option();
Expand Down
16 changes: 8 additions & 8 deletions tests/ui/consts/try-operator.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ LL | #![feature(const_convert)]
error[E0015]: `?` cannot determine the branch of `Result<(), ()>` in constant functions
--> $DIR/try-operator.rs:10:9
|
LL | Err(())?;
| ^^^^^^^^
LL | Err::<(), _>(())?;
| ^^^^^^^^^^^^^^^^^
|
note: impl defined here, but it is not `const`
--> $SRC_DIR/core/src/result.rs:LL:COL
Expand All @@ -21,8 +21,8 @@ LL + #![feature(effects)]
error[E0015]: `?` cannot convert from residual of `Result<bool, ()>` in constant functions
--> $DIR/try-operator.rs:10:9
|
LL | Err(())?;
| ^^^^^^^^
LL | Err::<(), _>(())?;
| ^^^^^^^^^^^^^^^^^
|
note: impl defined here, but it is not `const`
--> $SRC_DIR/core/src/result.rs:LL:COL
Expand All @@ -35,8 +35,8 @@ LL + #![feature(effects)]
error[E0015]: `?` cannot determine the branch of `Option<()>` in constant functions
--> $DIR/try-operator.rs:18:9
|
LL | None?;
| ^^^^^
LL | None::<()>?;
| ^^^^^^^^^^^
|
note: impl defined here, but it is not `const`
--> $SRC_DIR/core/src/option.rs:LL:COL
Expand All @@ -49,8 +49,8 @@ LL + #![feature(effects)]
error[E0015]: `?` cannot convert from residual of `Option<()>` in constant functions
--> $DIR/try-operator.rs:18:9
|
LL | None?;
| ^^^^^
LL | None::<()>?;
| ^^^^^^^^^^^
|
note: impl defined here, but it is not `const`
--> $SRC_DIR/core/src/option.rs:LL:COL
Expand Down
2 changes: 0 additions & 2 deletions tests/ui/did_you_mean/compatible-variants.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,6 @@ LL + Some(())
error[E0308]: `?` operator has incompatible types
--> $DIR/compatible-variants.rs:35:5
|
LL | fn d() -> Option<()> {
| ---------- expected `Option<()>` because of return type
LL | c()?
| ^^^^ expected `Option<()>`, found `()`
|
Expand Down
10 changes: 5 additions & 5 deletions tests/ui/impl-trait/cross-return-site-inference.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,34 @@

fn foo(b: bool) -> impl std::fmt::Debug {
if b {
return vec![42]
return vec![42];
}
[].into_iter().collect()
}

fn bar(b: bool) -> impl std::fmt::Debug {
if b {
return [].into_iter().collect()
return [].into_iter().collect();
}
vec![42]
}

fn bak(b: bool) -> impl std::fmt::Debug {
if b {
return std::iter::empty().collect()
return std::iter::empty().collect();
}
vec![42]
}

fn baa(b: bool) -> impl std::fmt::Debug {
if b {
return [42].into_iter().collect()
return [42].into_iter().collect();
}
vec![]
}

fn muh() -> Result<(), impl std::fmt::Debug> {
Err("whoops")?;
Err::<(), _>("whoops")?;
Ok(())
//~^ ERROR type annotations needed
}
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/inference/cannot-infer-closure.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
fn main() {
let x = |a: (), b: ()| {
Err(a)?;
Err::<(), _>(a)?;
Ok(b)
//~^ ERROR type annotations needed
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
error[E0308]: `?` operator has incompatible types
--> $DIR/issue-51632-try-desugar-incompatible-types.rs:8:5
|
LL | fn forbidden_narratives() -> Result<isize, ()> {
| ----------------- expected `Result<isize, ()>` because of return type
LL | missing_discourses()?
| ^^^^^^^^^^^^^^^^^^^^^ expected `Result<isize, ()>`, found `isize`
|
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/label/label_break_value_desugared_break.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
fn main() {
let _: Result<(), ()> = try {
'foo: {
Err(())?;
Err::<(), _>(())?;
break 'foo;
}
};

'foo: {
let _: Result<(), ()> = try {
Err(())?;
Err::<(), _>(())?;
break 'foo;
};
}
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/parser/try-with-nonterminal-block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ macro_rules! create_try {

fn main() {
let x: Option<&str> = create_try! {{
None?;
None::<()>?;
"Hello world"
}};

Expand Down
3 changes: 0 additions & 3 deletions tests/ui/suggestions/remove-question-symbol-with-paren.stderr
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
error[E0308]: `?` operator has incompatible types
--> $DIR/remove-question-symbol-with-paren.rs:5:6
|
LL | fn foo() -> Option<()> {
| ---------- expected `Option<()>` because of return type
LL | let x = Some(());
LL | (x?)
| ^^ expected `Option<()>`, found `()`
|
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/suggestions/suggest-box.fixed
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

fn main() {
let _x: Box<dyn Fn() -> Result<(), ()>> = Box::new(|| { //~ ERROR mismatched types
Err(())?;
Err::<(), _>(())?;
Ok(())
});
}
2 changes: 1 addition & 1 deletion tests/ui/suggestions/suggest-box.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

fn main() {
let _x: Box<dyn Fn() -> Result<(), ()>> = || { //~ ERROR mismatched types
Err(())?;
Err::<(), _>(())?;
Ok(())
};
}
4 changes: 2 additions & 2 deletions tests/ui/suggestions/suggest-box.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ LL | let _x: Box<dyn Fn() -> Result<(), ()>> = || {
| _____________-------------------------------___^
| | |
| | expected due to this
LL | | Err(())?;
LL | | Err::<(), _>(())?;
LL | | Ok(())
LL | | };
| |_____^ expected `Box<dyn Fn() -> Result<(), ()>>`, found closure
Expand All @@ -16,7 +16,7 @@ LL | | };
help: store this in the heap by calling `Box::new`
|
LL ~ let _x: Box<dyn Fn() -> Result<(), ()>> = Box::new(|| {
LL | Err(())?;
LL | Err::<(), _>(())?;
LL | Ok(())
LL ~ });
|
Expand Down
10 changes: 5 additions & 5 deletions tests/ui/try-block/try-block-bad-lifetime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ pub fn main() {
// result variable
let result: Result<(), &str> = try {
let my_string = String::from("");
let my_str: & str = & my_string;
let my_str: &str = &my_string;
//~^ ERROR `my_string` does not live long enough
Err(my_str) ?;
Err("") ?;
Err::<(), _>(my_str)?;
Err::<(), _>("")?;
};
do_something_with(result);
}
Expand All @@ -25,13 +25,13 @@ pub fn main() {
let mut i = 5;
let k = &mut i;
let mut j: Result<(), &mut i32> = try {
Err(k) ?;
Err::<(), _>(k)?;
i = 10; //~ ERROR cannot assign to `i` because it is borrowed
};
::std::mem::drop(k); //~ ERROR use of moved value: `k`
i = 40; //~ ERROR cannot assign to `i` because it is borrowed

let i_ptr = if let Err(i_ptr) = j { i_ptr } else { panic ! ("") };
let i_ptr = if let Err(i_ptr) = j { i_ptr } else { panic!("") };
*i_ptr = 50;
}
}
12 changes: 6 additions & 6 deletions tests/ui/try-block/try-block-bad-lifetime.stderr
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
error[E0597]: `my_string` does not live long enough
--> $DIR/try-block-bad-lifetime.rs:15:33
--> $DIR/try-block-bad-lifetime.rs:15:32
|
LL | let result: Result<(), &str> = try {
| ------ borrow later stored here
LL | let my_string = String::from("");
| --------- binding `my_string` declared here
LL | let my_str: & str = & my_string;
| ^^^^^^^^^^^ borrowed value does not live long enough
LL | let my_str: &str = &my_string;
| ^^^^^^^^^^ borrowed value does not live long enough
...
LL | };
| - `my_string` dropped here while still borrowed
Expand All @@ -29,8 +29,8 @@ error[E0382]: use of moved value: `k`
LL | let k = &mut i;
| - move occurs because `k` has type `&mut i32`, which does not implement the `Copy` trait
LL | let mut j: Result<(), &mut i32> = try {
LL | Err(k) ?;
| - value moved here
LL | Err::<(), _>(k)?;
| - value moved here
...
LL | ::std::mem::drop(k);
| ^ value used here after move
Expand All @@ -44,7 +44,7 @@ LL | let k = &mut i;
LL | i = 40;
| ^^^^^^ `i` is assigned to here but it was already borrowed
LL |
LL | let i_ptr = if let Err(i_ptr) = j { i_ptr } else { panic ! ("") };
LL | let i_ptr = if let Err(i_ptr) = j { i_ptr } else { panic!("") };
| - borrow later used here

error: aborting due to 4 previous errors
Expand Down
Loading

0 comments on commit b478d2b

Please sign in to comment.