Skip to content

Commit e0a9bd0

Browse files
committed
Auto merge of #49419 - leodasvacas:small-typeck-refactorings, r=nikomatsakis
Small typeck refactorings Some code improvements I noticed while reading the code.
2 parents ee1014e + 0a3eb5c commit e0a9bd0

File tree

2 files changed

+66
-83
lines changed

2 files changed

+66
-83
lines changed

src/librustc_typeck/check/mod.rs

+63-80
Original file line numberDiff line numberDiff line change
@@ -2507,7 +2507,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
25072507
sp: Span,
25082508
expr_sp: Span,
25092509
fn_inputs: &[Ty<'tcx>],
2510-
expected_arg_tys: &[Ty<'tcx>],
2510+
mut expected_arg_tys: &[Ty<'tcx>],
25112511
args: &'gcx [hir::Expr],
25122512
variadic: bool,
25132513
tuple_arguments: TupleArgumentsFlag,
@@ -2528,19 +2528,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
25282528
self.register_wf_obligation(fn_input_ty, sp, traits::MiscObligation);
25292529
}
25302530

2531-
let mut expected_arg_tys = expected_arg_tys;
25322531
let expected_arg_count = fn_inputs.len();
25332532

2534-
fn parameter_count_error<'tcx>(sess: &Session,
2535-
sp: Span,
2536-
expr_sp: Span,
2537-
expected_count: usize,
2538-
arg_count: usize,
2539-
error_code: &str,
2540-
variadic: bool,
2541-
def_span: Option<Span>,
2542-
sugg_unit: bool) {
2543-
let mut err = sess.struct_span_err_with_code(sp,
2533+
let param_count_error = |expected_count: usize,
2534+
arg_count: usize,
2535+
error_code: &str,
2536+
variadic: bool,
2537+
sugg_unit: bool| {
2538+
let mut err = tcx.sess.struct_span_err_with_code(sp,
25442539
&format!("this function takes {}{} parameter{} but {} parameter{} supplied",
25452540
if variadic {"at least "} else {""},
25462541
expected_count,
@@ -2549,11 +2544,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
25492544
if arg_count == 1 {" was"} else {"s were"}),
25502545
DiagnosticId::Error(error_code.to_owned()));
25512546

2552-
if let Some(def_s) = def_span.map(|sp| sess.codemap().def_span(sp)) {
2547+
if let Some(def_s) = def_span.map(|sp| tcx.sess.codemap().def_span(sp)) {
25532548
err.span_label(def_s, "defined here");
25542549
}
25552550
if sugg_unit {
2556-
let sugg_span = sess.codemap().end_point(expr_sp);
2551+
let sugg_span = tcx.sess.codemap().end_point(expr_sp);
25572552
// remove closing `)` from the span
25582553
let sugg_span = sugg_span.shrink_to_lo();
25592554
err.span_suggestion(
@@ -2567,14 +2562,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
25672562
if expected_count == 1 {""} else {"s"}));
25682563
}
25692564
err.emit();
2570-
}
2565+
};
25712566

25722567
let formal_tys = if tuple_arguments == TupleArguments {
25732568
let tuple_type = self.structurally_resolved_type(sp, fn_inputs[0]);
25742569
match tuple_type.sty {
25752570
ty::TyTuple(arg_types) if arg_types.len() != args.len() => {
2576-
parameter_count_error(tcx.sess, sp, expr_sp, arg_types.len(), args.len(),
2577-
"E0057", false, def_span, false);
2571+
param_count_error(arg_types.len(), args.len(), "E0057", false, false);
25782572
expected_arg_tys = &[];
25792573
self.err_args(args.len())
25802574
}
@@ -2602,8 +2596,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
26022596
if supplied_arg_count >= expected_arg_count {
26032597
fn_inputs.to_vec()
26042598
} else {
2605-
parameter_count_error(tcx.sess, sp, expr_sp, expected_arg_count,
2606-
supplied_arg_count, "E0060", true, def_span, false);
2599+
param_count_error(expected_arg_count, supplied_arg_count, "E0060", true, false);
26072600
expected_arg_tys = &[];
26082601
self.err_args(supplied_arg_count)
26092602
}
@@ -2616,11 +2609,17 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
26162609
} else {
26172610
false
26182611
};
2619-
parameter_count_error(tcx.sess, sp, expr_sp, expected_arg_count,
2620-
supplied_arg_count, "E0061", false, def_span, sugg_unit);
2612+
param_count_error(expected_arg_count, supplied_arg_count, "E0061", false, sugg_unit);
2613+
26212614
expected_arg_tys = &[];
26222615
self.err_args(supplied_arg_count)
26232616
};
2617+
// If there is no expectation, expect formal_tys.
2618+
let expected_arg_tys = if !expected_arg_tys.is_empty() {
2619+
expected_arg_tys
2620+
} else {
2621+
&formal_tys
2622+
};
26242623

26252624
debug!("check_argument_types: formal_tys={:?}",
26262625
formal_tys.iter().map(|t| self.ty_to_string(*t)).collect::<Vec<String>>());
@@ -2672,28 +2671,21 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
26722671

26732672
// The special-cased logic below has three functions:
26742673
// 1. Provide as good of an expected type as possible.
2675-
let expected = expected_arg_tys.get(i).map(|&ty| {
2676-
Expectation::rvalue_hint(self, ty)
2677-
});
2674+
let expected = Expectation::rvalue_hint(self, expected_arg_tys[i]);
26782675

2679-
let checked_ty = self.check_expr_with_expectation(
2680-
&arg,
2681-
expected.unwrap_or(ExpectHasType(formal_ty)));
2676+
let checked_ty = self.check_expr_with_expectation(&arg, expected);
26822677

26832678
// 2. Coerce to the most detailed type that could be coerced
26842679
// to, which is `expected_ty` if `rvalue_hint` returns an
26852680
// `ExpectHasType(expected_ty)`, or the `formal_ty` otherwise.
2686-
let coerce_ty = expected.and_then(|e| e.only_has_type(self));
2681+
let coerce_ty = expected.only_has_type(self).unwrap_or(formal_ty);
26872682
// We're processing function arguments so we definitely want to use
26882683
// two-phase borrows.
2689-
self.demand_coerce(&arg,
2690-
checked_ty,
2691-
coerce_ty.unwrap_or(formal_ty),
2692-
AllowTwoPhase::Yes);
2684+
self.demand_coerce(&arg, checked_ty, coerce_ty, AllowTwoPhase::Yes);
26932685

26942686
// 3. Relate the expected type and the formal one,
26952687
// if the expected type was used for the coercion.
2696-
coerce_ty.map(|ty| self.demand_suptype(arg.span, formal_ty, ty));
2688+
self.demand_suptype(arg.span, formal_ty, coerce_ty);
26972689
}
26982690
}
26992691

@@ -2839,18 +2831,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
28392831
fn check_expr_coercable_to_type(&self,
28402832
expr: &'gcx hir::Expr,
28412833
expected: Ty<'tcx>) -> Ty<'tcx> {
2842-
self.check_expr_coercable_to_type_with_needs(expr, expected, Needs::None)
2843-
}
2844-
2845-
fn check_expr_coercable_to_type_with_needs(&self,
2846-
expr: &'gcx hir::Expr,
2847-
expected: Ty<'tcx>,
2848-
needs: Needs)
2849-
-> Ty<'tcx> {
2850-
let ty = self.check_expr_with_expectation_and_needs(
2851-
expr,
2852-
ExpectHasType(expected),
2853-
needs);
2834+
let ty = self.check_expr_with_hint(expr, expected);
28542835
// checks don't need two phase
28552836
self.demand_coerce(expr, ty, expected, AllowTwoPhase::No)
28562837
}
@@ -2900,45 +2881,47 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
29002881
formal_args: &[Ty<'tcx>])
29012882
-> Vec<Ty<'tcx>> {
29022883
let formal_ret = self.resolve_type_vars_with_obligations(formal_ret);
2903-
let expected_args = expected_ret.only_has_type(self).and_then(|ret_ty| {
2904-
self.fudge_regions_if_ok(&RegionVariableOrigin::Coercion(call_span), || {
2905-
// Attempt to apply a subtyping relationship between the formal
2906-
// return type (likely containing type variables if the function
2907-
// is polymorphic) and the expected return type.
2908-
// No argument expectations are produced if unification fails.
2909-
let origin = self.misc(call_span);
2910-
let ures = self.at(&origin, self.param_env).sup(ret_ty, &formal_ret);
2911-
2912-
// FIXME(#27336) can't use ? here, Try::from_error doesn't default
2913-
// to identity so the resulting type is not constrained.
2914-
match ures {
2915-
Ok(ok) => {
2916-
// Process any obligations locally as much as
2917-
// we can. We don't care if some things turn
2918-
// out unconstrained or ambiguous, as we're
2919-
// just trying to get hints here.
2920-
self.save_and_restore_in_snapshot_flag(|_| {
2921-
let mut fulfill = TraitEngine::new(self.tcx);
2922-
for obligation in ok.obligations {
2923-
fulfill.register_predicate_obligation(self, obligation);
2924-
}
2925-
fulfill.select_where_possible(self)
2926-
}).map_err(|_| ())?;
2927-
}
2928-
Err(_) => return Err(()),
2884+
let ret_ty = match expected_ret.only_has_type(self) {
2885+
Some(ret) => ret,
2886+
None => return Vec::new()
2887+
};
2888+
let expect_args = self.fudge_regions_if_ok(&RegionVariableOrigin::Coercion(call_span), || {
2889+
// Attempt to apply a subtyping relationship between the formal
2890+
// return type (likely containing type variables if the function
2891+
// is polymorphic) and the expected return type.
2892+
// No argument expectations are produced if unification fails.
2893+
let origin = self.misc(call_span);
2894+
let ures = self.at(&origin, self.param_env).sup(ret_ty, &formal_ret);
2895+
2896+
// FIXME(#27336) can't use ? here, Try::from_error doesn't default
2897+
// to identity so the resulting type is not constrained.
2898+
match ures {
2899+
Ok(ok) => {
2900+
// Process any obligations locally as much as
2901+
// we can. We don't care if some things turn
2902+
// out unconstrained or ambiguous, as we're
2903+
// just trying to get hints here.
2904+
self.save_and_restore_in_snapshot_flag(|_| {
2905+
let mut fulfill = TraitEngine::new(self.tcx);
2906+
for obligation in ok.obligations {
2907+
fulfill.register_predicate_obligation(self, obligation);
2908+
}
2909+
fulfill.select_where_possible(self)
2910+
}).map_err(|_| ())?;
29292911
}
2912+
Err(_) => return Err(()),
2913+
}
29302914

2931-
// Record all the argument types, with the substitutions
2932-
// produced from the above subtyping unification.
2933-
Ok(formal_args.iter().map(|ty| {
2934-
self.resolve_type_vars_if_possible(ty)
2935-
}).collect())
2936-
}).ok()
2937-
}).unwrap_or(vec![]);
2915+
// Record all the argument types, with the substitutions
2916+
// produced from the above subtyping unification.
2917+
Ok(formal_args.iter().map(|ty| {
2918+
self.resolve_type_vars_if_possible(ty)
2919+
}).collect())
2920+
}).unwrap_or(Vec::new());
29382921
debug!("expected_inputs_for_expected_output(formal={:?} -> {:?}, expected={:?} -> {:?})",
29392922
formal_args, formal_ret,
2940-
expected_args, expected_ret);
2941-
expected_args
2923+
expect_args, expected_ret);
2924+
expect_args
29422925
}
29432926

29442927
// Checks a method call.

src/librustc_typeck/check/op.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -174,9 +174,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
174174
// trait matching creating lifetime constraints that are too strict.
175175
// E.g. adding `&'a T` and `&'b T`, given `&'x T: Add<&'x T>`, will result
176176
// in `&'a T <: &'x T` and `&'b T <: &'x T`, instead of `'a = 'b = 'x`.
177-
let lhs_ty = self.check_expr_coercable_to_type_with_needs(lhs_expr,
178-
self.next_ty_var(TypeVariableOrigin::MiscVariable(lhs_expr.span)),
179-
lhs_needs);
177+
let lhs_ty = self.check_expr_with_needs(lhs_expr, lhs_needs);
178+
let fresh_var = self.next_ty_var(TypeVariableOrigin::MiscVariable(lhs_expr.span));
179+
let lhs_ty = self.demand_coerce(lhs_expr, lhs_ty, fresh_var, AllowTwoPhase::No);
180180
let lhs_ty = self.resolve_type_vars_with_obligations(lhs_ty);
181181

182182
// NB: As we have not yet type-checked the RHS, we don't have the

0 commit comments

Comments
 (0)