Skip to content

Commit b03ccac

Browse files
committed
Auto merge of #88266 - nikomatsakis:issue-87879, r=jackh726
resolve type variables after checking casts r? `@jackh726` Fixes #87814 Fixes #88118 Supercedes #87879 (cc `@ldm0)`
2 parents 0599f34 + ec9531b commit b03ccac

File tree

11 files changed

+69
-8
lines changed

11 files changed

+69
-8
lines changed

Diff for: compiler/rustc_typeck/src/check/_match.rs

+2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use rustc_trait_selection::traits::{
1414
};
1515

1616
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
17+
#[instrument(skip(self), level = "debug")]
1718
pub fn check_match(
1819
&self,
1920
expr: &'tcx hir::Expr<'tcx>,
@@ -26,6 +27,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2627

2728
let acrb = arms_contain_ref_bindings(arms);
2829
let scrutinee_ty = self.demand_scrutinee_type(scrut, acrb, arms.is_empty());
30+
debug!(?scrutinee_ty);
2931

3032
// If there are no arms, that is a diverging match; a special case.
3133
if arms.is_empty() {

Diff for: compiler/rustc_typeck/src/check/cast.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ use rustc_trait_selection::traits::error_reporting::report_object_safety_error;
5151

5252
/// Reifies a cast check to be checked once we have full type information for
5353
/// a function context.
54+
#[derive(Debug)]
5455
pub struct CastCheck<'tcx> {
5556
expr: &'tcx hir::Expr<'tcx>,
5657
expr_ty: Ty<'tcx>,
@@ -603,12 +604,11 @@ impl<'a, 'tcx> CastCheck<'tcx> {
603604
});
604605
}
605606

607+
#[instrument(skip(fcx), level = "debug")]
606608
pub fn check(mut self, fcx: &FnCtxt<'a, 'tcx>) {
607609
self.expr_ty = fcx.structurally_resolved_type(self.expr.span, self.expr_ty);
608610
self.cast_ty = fcx.structurally_resolved_type(self.cast_span, self.cast_ty);
609611

610-
debug!("check_cast({}, {:?} as {:?})", self.expr.hir_id, self.expr_ty, self.cast_ty);
611-
612612
if !fcx.type_is_known_to_be_sized_modulo_regions(self.cast_ty, self.span) {
613613
self.report_cast_to_unsized_type(fcx);
614614
} else if self.expr_ty.references_error() || self.cast_ty.references_error() {

Diff for: compiler/rustc_typeck/src/check/coercion.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1328,6 +1328,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
13281328
/// The inner coercion "engine". If `expression` is `None`, this
13291329
/// is a forced-unit case, and hence `expression_ty` must be
13301330
/// `Nil`.
1331+
#[instrument(skip(self, fcx, augment_error, label_expression_as_expected), level = "debug")]
13311332
crate fn coerce_inner<'a>(
13321333
&mut self,
13331334
fcx: &FnCtxt<'a, 'tcx>,

Diff for: compiler/rustc_typeck/src/check/expr.rs

+21-2
Original file line numberDiff line numberDiff line change
@@ -156,12 +156,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
156156
/// Note that inspecting a type's structure *directly* may expose the fact
157157
/// that there are actually multiple representations for `Error`, so avoid
158158
/// that when err needs to be handled differently.
159+
#[instrument(skip(self), level = "debug")]
159160
pub(super) fn check_expr_with_expectation(
160161
&self,
161162
expr: &'tcx hir::Expr<'tcx>,
162163
expected: Expectation<'tcx>,
163164
) -> Ty<'tcx> {
164-
debug!(">> type-checking: expected={:?}, expr={:?} ", expected, expr);
165+
if self.tcx().sess.verbose() {
166+
// make this code only run with -Zverbose because it is probably slow
167+
if let Ok(lint_str) = self.tcx.sess.source_map().span_to_snippet(expr.span) {
168+
if !lint_str.contains("\n") {
169+
debug!("expr text: {}", lint_str);
170+
} else {
171+
let mut lines = lint_str.lines();
172+
if let Some(line0) = lines.next() {
173+
let remaining_lines = lines.count();
174+
debug!("expr text: {}", line0);
175+
debug!("expr text: ...(and {} more lines)", remaining_lines);
176+
}
177+
}
178+
}
179+
}
165180

166181
// True if `expr` is a `Try::from_ok(())` that is a result of desugaring a try block
167182
// without the final expr (e.g. `try { return; }`). We don't want to generate an
@@ -1039,7 +1054,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10391054
let t_cast = self.to_ty_saving_user_provided_ty(t);
10401055
let t_cast = self.resolve_vars_if_possible(t_cast);
10411056
let t_expr = self.check_expr_with_expectation(e, ExpectCastableToType(t_cast));
1042-
let t_cast = self.resolve_vars_if_possible(t_cast);
1057+
let t_expr = self.resolve_vars_if_possible(t_expr);
10431058

10441059
// Eagerly check for some obvious errors.
10451060
if t_expr.references_error() || t_cast.references_error() {
@@ -1049,6 +1064,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10491064
let mut deferred_cast_checks = self.deferred_cast_checks.borrow_mut();
10501065
match cast::CastCheck::new(self, e, t_expr, t_cast, t.span, expr.span) {
10511066
Ok(cast_check) => {
1067+
debug!(
1068+
"check_expr_cast: deferring cast from {:?} to {:?}: {:?}",
1069+
t_cast, t_expr, cast_check,
1070+
);
10521071
deferred_cast_checks.push(cast_check);
10531072
t_cast
10541073
}

Diff for: compiler/rustc_typeck/src/check/fallback.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ use rustc_infer::infer::type_variable::Diverging;
33
use rustc_middle::ty::{self, Ty};
44

55
impl<'tcx> FnCtxt<'_, 'tcx> {
6-
pub(super) fn type_inference_fallback(&self) {
6+
/// Performs type inference fallback, returning true if any fallback
7+
/// occurs.
8+
pub(super) fn type_inference_fallback(&self) -> bool {
79
// All type checking constraints were added, try to fallback unsolved variables.
810
self.select_obligations_where_possible(false, |_| {});
911
let mut fallback_has_occurred = false;
@@ -50,6 +52,8 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
5052

5153
// See if we can make any more progress.
5254
self.select_obligations_where_possible(fallback_has_occurred, |_| {});
55+
56+
fallback_has_occurred
5357
}
5458

5559
// Tries to apply a fallback to `ty` if it is an unsolved variable.

Diff for: compiler/rustc_typeck/src/check/fn_ctxt/checks.rs

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ use std::slice;
2929
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3030
pub(in super::super) fn check_casts(&self) {
3131
let mut deferred_cast_checks = self.deferred_cast_checks.borrow_mut();
32+
debug!("FnCtxt::check_casts: {} deferred checks", deferred_cast_checks.len());
3233
for cast in deferred_cast_checks.drain(..) {
3334
cast.check(self);
3435
}

Diff for: compiler/rustc_typeck/src/check/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -446,11 +446,12 @@ fn typeck_with_fallback<'tcx>(
446446
fcx
447447
};
448448

449-
fcx.type_inference_fallback();
449+
let fallback_has_occurred = fcx.type_inference_fallback();
450450

451451
// Even though coercion casts provide type hints, we check casts after fallback for
452452
// backwards compatibility. This makes fallback a stronger type hint than a cast coercion.
453453
fcx.check_casts();
454+
fcx.select_obligations_where_possible(fallback_has_occurred, |_| {});
454455

455456
// Closure and generator analysis may run after fallback
456457
// because they don't constrain other type variables.

Diff for: compiler/rustc_typeck/src/expr_use_visitor.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -120,9 +120,8 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
120120
}
121121
}
122122

123+
#[instrument(skip(self), level = "debug")]
123124
pub fn consume_body(&mut self, body: &hir::Body<'_>) {
124-
debug!("consume_body(body={:?})", body);
125-
126125
for param in body.params {
127126
let param_ty = return_if_err!(self.mc.pat_ty_adjusted(&param.pat));
128127
debug!("consume_body: param_ty = {:?}", param_ty);
+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Regression test for #88118. Used to ICE.
2+
//
3+
// check-pass
4+
5+
#![allow(incomplete_features)]
6+
#![feature(capture_disjoint_fields)]
7+
8+
fn foo<MsU>(handler: impl FnOnce() -> MsU + Clone + 'static) {
9+
Box::new(move |value| {
10+
(|_| handler.clone()())(value);
11+
None
12+
}) as Box<dyn Fn(i32) -> Option<i32>>;
13+
}
14+
15+
fn main() {}

Diff for: src/test/ui/closures/issue-87814-1.rs

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// check-pass
2+
fn main() {
3+
let mut schema_all = vec![];
4+
(0..42).for_each(|_x| match Err(()) as Result<(), _> {
5+
Ok(()) => schema_all.push(()),
6+
Err(_) => (),
7+
});
8+
}

Diff for: src/test/ui/closures/issue-87814-2.rs

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// check-pass
2+
#![feature(try_reserve)]
3+
4+
fn main() {
5+
let mut schema_all: (Vec<String>, Vec<String>) = (vec![], vec![]);
6+
7+
let _c = || match schema_all.0.try_reserve(1) as Result<(), _> {
8+
Ok(()) => (),
9+
Err(_) => (),
10+
};
11+
}

0 commit comments

Comments
 (0)