Rollup merge of #54641 - ljedrz:cleanup_rustc_infer, r=estebank

A few cleanups and minor improvements to rustc/infer

- use unwrap_or(_else) where applicable
- convert single-branch matches to if-let
- use to_owned instead of to_string with string literals
- improve vector allocations
- readability improvements
- miscellaneous minor code improvements
This commit is contained in:
kennytm 2018-10-01 16:13:00 +08:00 committed by GitHub
commit 41706ff12b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 172 additions and 202 deletions

View file

@ -135,10 +135,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
);
// Select everything, returning errors.
let true_errors = match fulfill_cx.select_where_possible(self) {
Ok(()) => vec![],
Err(errors) => errors,
};
let true_errors = fulfill_cx.select_where_possible(self).err().unwrap_or_else(Vec::new);
debug!("true_errors = {:#?}", true_errors);
if !true_errors.is_empty() {
@ -148,10 +145,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
}
// Anything left unselected *now* must be an ambiguity.
let ambig_errors = match fulfill_cx.select_all_or_error(self) {
Ok(()) => vec![],
Err(errors) => errors,
};
let ambig_errors = fulfill_cx.select_all_or_error(self).err().unwrap_or_else(Vec::new);
debug!("ambig_errors = {:#?}", ambig_errors);
let region_obligations = self.take_registered_region_obligations();
@ -316,16 +310,18 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
}
// ...also include the other query region constraints from the query.
output_query_region_constraints.reserve(query_result.value.region_constraints.len());
for r_c in query_result.value.region_constraints.iter() {
let &ty::OutlivesPredicate(k1, r2) = r_c.skip_binder(); // reconstructed below
let k1 = substitute_value(self.tcx, &result_subst, &k1);
let r2 = substitute_value(self.tcx, &result_subst, &r2);
if k1 != r2.into() {
output_query_region_constraints
.push(ty::Binder::bind(ty::OutlivesPredicate(k1, r2)));
}
}
output_query_region_constraints.extend(
query_result.value.region_constraints.iter().filter_map(|r_c| {
let &ty::OutlivesPredicate(k1, r2) = r_c.skip_binder(); // reconstructed below
let k1 = substitute_value(self.tcx, &result_subst, &k1);
let r2 = substitute_value(self.tcx, &result_subst, &r2);
if k1 != r2.into() {
Some(ty::Binder::bind(ty::OutlivesPredicate(k1, r2)))
} else {
None
}
})
);
let user_result: R =
query_result.substitute_projected(self.tcx, &result_subst, |q_r| &q_r.value);
@ -448,10 +444,9 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
.variables
.iter()
.enumerate()
.map(|(index, info)| match opt_values[CanonicalVar::new(index)] {
Some(k) => k,
None => self.fresh_inference_var_for_canonical_var(cause.span, *info),
})
.map(|(index, info)| opt_values[CanonicalVar::new(index)].unwrap_or_else(||
self.fresh_inference_var_for_canonical_var(cause.span, *info)
))
.collect(),
};
@ -504,24 +499,22 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
let ty::OutlivesPredicate(k1, r2) = constraint.skip_binder(); // restored below
let k1 = substitute_value(self.tcx, result_subst, k1);
let r2 = substitute_value(self.tcx, result_subst, r2);
match k1.unpack() {
UnpackedKind::Lifetime(r1) => Obligation::new(
cause.clone(),
param_env,
ty::Predicate::RegionOutlives(ty::Binder::dummy(
ty::OutlivesPredicate(r1, r2),
)),
),
UnpackedKind::Type(t1) => Obligation::new(
cause.clone(),
param_env,
ty::Predicate::TypeOutlives(ty::Binder::dummy(ty::OutlivesPredicate(
t1, r2,
))),
),
}
}),
Obligation::new(
cause.clone(),
param_env,
match k1.unpack() {
UnpackedKind::Lifetime(r1) => ty::Predicate::RegionOutlives(
ty::Binder::dummy(
ty::OutlivesPredicate(r1, r2)
)),
UnpackedKind::Type(t1) => ty::Predicate::TypeOutlives(
ty::Binder::dummy(ty::OutlivesPredicate(
t1, r2
)))
}
)
})
) as Box<dyn Iterator<Item = _>>
}
@ -583,31 +576,30 @@ pub fn make_query_outlives<'tcx>(
assert!(verifys.is_empty());
assert!(givens.is_empty());
let mut outlives: Vec<_> = constraints
.into_iter()
.map(|(k, _)| match *k {
// Swap regions because we are going from sub (<=) to outlives
// (>=).
Constraint::VarSubVar(v1, v2) => ty::OutlivesPredicate(
tcx.mk_region(ty::ReVar(v2)).into(),
tcx.mk_region(ty::ReVar(v1)),
),
Constraint::VarSubReg(v1, r2) => {
ty::OutlivesPredicate(r2.into(), tcx.mk_region(ty::ReVar(v1)))
}
Constraint::RegSubVar(r1, v2) => {
ty::OutlivesPredicate(tcx.mk_region(ty::ReVar(v2)).into(), r1)
}
Constraint::RegSubReg(r1, r2) => ty::OutlivesPredicate(r2.into(), r1),
})
.map(ty::Binder::dummy) // no bound regions in the code above
.collect();
outlives.extend(
outlives_obligations
.map(|(ty, r)| ty::OutlivesPredicate(ty.into(), r))
.map(ty::Binder::dummy), // no bound regions in the code above
);
let outlives: Vec<_> = constraints
.into_iter()
.map(|(k, _)| match *k {
// Swap regions because we are going from sub (<=) to outlives
// (>=).
Constraint::VarSubVar(v1, v2) => ty::OutlivesPredicate(
tcx.mk_region(ty::ReVar(v2)).into(),
tcx.mk_region(ty::ReVar(v1)),
),
Constraint::VarSubReg(v1, r2) => {
ty::OutlivesPredicate(r2.into(), tcx.mk_region(ty::ReVar(v1)))
}
Constraint::RegSubVar(r1, v2) => {
ty::OutlivesPredicate(tcx.mk_region(ty::ReVar(v2)).into(), r1)
}
Constraint::RegSubReg(r1, r2) => ty::OutlivesPredicate(r2.into(), r1),
})
.map(ty::Binder::dummy) // no bound regions in the code above
.chain(
outlives_obligations
.map(|(ty, r)| ty::OutlivesPredicate(ty.into(), r))
.map(ty::Binder::dummy), // no bound regions in the code above
)
.collect();
outlives
}

View file

@ -77,24 +77,22 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx>
match (&a.sty, &b.sty) {
(&ty::Infer(TyVar(a_id)), &ty::Infer(TyVar(b_id))) => {
infcx.type_variables.borrow_mut().equate(a_id, b_id);
Ok(a)
}
(&ty::Infer(TyVar(a_id)), _) => {
self.fields.instantiate(b, RelationDir::EqTo, a_id, self.a_is_expected)?;
Ok(a)
}
(_, &ty::Infer(TyVar(b_id))) => {
self.fields.instantiate(a, RelationDir::EqTo, b_id, self.a_is_expected)?;
Ok(a)
}
_ => {
self.fields.infcx.super_combine_tys(self, a, b)?;
Ok(a)
}
}
Ok(a)
}
fn regions(&mut self, a: ty::Region<'tcx>, b: ty::Region<'tcx>)

View file

@ -406,10 +406,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
errors.clone()
} else {
errors
.iter()
.filter(|&e| !is_bound_failure(e))
.cloned()
.collect()
.iter()
.filter(|&e| !is_bound_failure(e))
.cloned()
.collect()
};
// sort the errors by span, for better error message stability.
@ -455,11 +455,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
TypeError::Sorts(ref exp_found) => {
// if they are both "path types", there's a chance of ambiguity
// due to different versions of the same crate
match (&exp_found.expected.sty, &exp_found.found.sty) {
(&ty::Adt(exp_adt, _), &ty::Adt(found_adt, _)) => {
report_path_match(err, exp_adt.did, found_adt.did);
}
_ => (),
if let (&ty::Adt(exp_adt, _), &ty::Adt(found_adt, _))
= (&exp_found.expected.sty, &exp_found.found.sty)
{
report_path_match(err, exp_adt.did, found_adt.did);
}
}
TypeError::Traits(ref exp_found) => {

View file

@ -100,7 +100,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
let mut labels = vec![(
span,
if &name == "_" {
"cannot infer type".to_string()
"cannot infer type".to_owned()
} else {
format!("cannot infer type for `{}`", name)
},
@ -138,7 +138,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
// ```
labels.clear();
labels.push(
(pattern.span, "consider giving this closure parameter a type".to_string()));
(pattern.span, "consider giving this closure parameter a type".to_owned()));
} else if let Some(pattern) = local_visitor.found_local_pattern {
if let Some(simple_ident) = pattern.simple_ident() {
match pattern.span.compiler_desugaring_kind() {
@ -146,12 +146,12 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
format!("consider giving `{}` a type", simple_ident))),
Some(CompilerDesugaringKind::ForLoop) => labels.push((
pattern.span,
"the element type for this iterator is not specified".to_string(),
"the element type for this iterator is not specified".to_owned(),
)),
_ => {}
}
} else {
labels.push((pattern.span, "consider giving the pattern a type".to_string()));
labels.push((pattern.span, "consider giving the pattern a type".to_owned()));
}
}

View file

@ -113,12 +113,12 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
(None, None) => {
let (main_label_1, span_label_1) = if ty_sup.id == ty_sub.id {
(
"this type is declared with multiple lifetimes...".to_string(),
"...but data with one lifetime flows into the other here".to_string()
"this type is declared with multiple lifetimes...".to_owned(),
"...but data with one lifetime flows into the other here".to_owned()
)
} else {
(
"these two types are declared with different lifetimes...".to_string(),
"these two types are declared with different lifetimes...".to_owned(),
format!(
"...but data{} flows{} here",
span_label_var1,
@ -133,7 +133,7 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
ty_sub.span,
ret_span,
"this parameter and the return type are declared \
with different lifetimes...".to_string()
with different lifetimes...".to_owned()
,
format!("...but data{} is returned here", span_label_var1),
),
@ -141,7 +141,7 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
ty_sup.span,
ret_span,
"this parameter and the return type are declared \
with different lifetimes...".to_string()
with different lifetimes...".to_owned()
,
format!("...but data{} is returned here", span_label_var1),
),

View file

@ -58,18 +58,17 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
&RegionKind::ReFree(ref free_region)) = (&sub_origin, sup_region) {
let hir = &self.tcx.hir;
if let Some(node_id) = hir.as_local_node_id(free_region.scope) {
match hir.get(node_id) {
Node::Expr(Expr {
node: Closure(_, _, _, closure_span, None),
..
}) => {
let sup_sp = sup_origin.span();
let origin_sp = origin.span();
let mut err = self.tcx.sess.struct_span_err(
sup_sp,
"borrowed data cannot be stored outside of its closure");
err.span_label(sup_sp, "cannot be stored outside of its closure");
if origin_sp == sup_sp || origin_sp.contains(sup_sp) {
if let Node::Expr(Expr {
node: Closure(_, _, _, closure_span, None),
..
}) = hir.get(node_id) {
let sup_sp = sup_origin.span();
let origin_sp = origin.span();
let mut err = self.tcx.sess.struct_span_err(
sup_sp,
"borrowed data cannot be stored outside of its closure");
err.span_label(sup_sp, "cannot be stored outside of its closure");
if origin_sp == sup_sp || origin_sp.contains(sup_sp) {
// // sup_sp == origin.span():
//
// let mut x = None;
@ -87,11 +86,11 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
// ------------ ... because it cannot outlive this closure
// f = Some(x);
// ^ cannot be stored outside of its closure
err.span_label(*external_span,
"borrowed data cannot be stored into here...");
err.span_label(*closure_span,
"...because it cannot outlive this closure");
} else {
err.span_label(*external_span,
"borrowed data cannot be stored into here...");
err.span_label(*closure_span,
"...because it cannot outlive this closure");
} else {
// FIXME: the wording for this case could be much improved
//
// let mut lines_to_use: Vec<&CrateId> = Vec::new();
@ -102,18 +101,16 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
// ...so that variable is valid at time of its declaration
// lines_to_use.push(installed_id);
// ^^^^^^^^^^^^ cannot be stored outside of its closure
err.span_label(origin_sp,
"cannot infer an appropriate lifetime...");
err.span_label(*external_span,
"...so that variable is valid at time of its \
declaration");
err.span_label(*closure_span,
"borrowed data cannot outlive this closure");
}
err.emit();
return Some(ErrorReported);
err.span_label(origin_sp,
"cannot infer an appropriate lifetime...");
err.span_label(*external_span,
"...so that variable is valid at time of its \
declaration");
err.span_label(*closure_span,
"borrowed data cannot outlive this closure");
}
_ => {}
err.emit();
return Some(ErrorReported);
}
}
}

View file

@ -20,64 +20,62 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
/// Print the error message for lifetime errors when the return type is a static impl Trait.
pub(super) fn try_report_static_impl_trait(&self) -> Option<ErrorReported> {
if let Some(ref error) = self.error {
match error.clone() {
RegionResolutionError::SubSupConflict(
if let RegionResolutionError::SubSupConflict(
var_origin,
sub_origin,
sub_r,
sup_origin,
sup_r,
) => {
let anon_reg_sup = self.tcx.is_suitable_region(sup_r)?;
if sub_r == &RegionKind::ReStatic &&
self.tcx.return_type_impl_trait(anon_reg_sup.def_id).is_some()
{
let sp = var_origin.span();
let return_sp = sub_origin.span();
let mut err = self.tcx.sess.struct_span_err(
sp,
"cannot infer an appropriate lifetime",
);
err.span_label(
return_sp,
"this return type evaluates to the `'static` lifetime...",
);
err.span_label(
sup_origin.span(),
"...but this borrow...",
);
) = error.clone()
{
let anon_reg_sup = self.tcx.is_suitable_region(sup_r)?;
if sub_r == &RegionKind::ReStatic &&
self.tcx.return_type_impl_trait(anon_reg_sup.def_id).is_some()
{
let sp = var_origin.span();
let return_sp = sub_origin.span();
let mut err = self.tcx.sess.struct_span_err(
sp,
"cannot infer an appropriate lifetime",
);
err.span_label(
return_sp,
"this return type evaluates to the `'static` lifetime...",
);
err.span_label(
sup_origin.span(),
"...but this borrow...",
);
let (lifetime, lt_sp_opt) = self.tcx.msg_span_from_free_region(sup_r);
if let Some(lifetime_sp) = lt_sp_opt {
err.span_note(
lifetime_sp,
&format!("...can't outlive {}", lifetime),
);
}
let lifetime_name = match sup_r {
RegionKind::ReFree(FreeRegion {
bound_region: BoundRegion::BrNamed(_, ref name), ..
}) => name.to_string(),
_ => "'_".to_owned(),
};
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(return_sp) {
err.span_suggestion_with_applicability(
return_sp,
&format!(
"you can add a constraint to the return type to make it last \
less than `'static` and match {}",
lifetime,
),
format!("{} + {}", snippet, lifetime_name),
Applicability::Unspecified,
);
}
err.emit();
return Some(ErrorReported);
let (lifetime, lt_sp_opt) = self.tcx.msg_span_from_free_region(sup_r);
if let Some(lifetime_sp) = lt_sp_opt {
err.span_note(
lifetime_sp,
&format!("...can't outlive {}", lifetime),
);
}
let lifetime_name = match sup_r {
RegionKind::ReFree(FreeRegion {
bound_region: BoundRegion::BrNamed(_, ref name), ..
}) => name.to_string(),
_ => "'_".to_owned(),
};
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(return_sp) {
err.span_suggestion_with_applicability(
return_sp,
&format!(
"you can add a constraint to the return type to make it last \
less than `'static` and match {}",
lifetime,
),
format!("{} + {}", snippet, lifetime_name),
Applicability::Unspecified,
);
}
err.emit();
return Some(ErrorReported);
}
_ => {}
}
}
None

View file

@ -119,16 +119,13 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
decl: &hir::FnDecl,
) -> Option<Span> {
let ret_ty = self.tcx.type_of(scope_def_id);
match ret_ty.sty {
ty::FnDef(_, _) => {
let sig = ret_ty.fn_sig(self.tcx);
let late_bound_regions = self.tcx
.collect_referenced_late_bound_regions(&sig.output());
if late_bound_regions.iter().any(|r| *r == br) {
return Some(decl.output.span());
}
if let ty::FnDef(_, _) = ret_ty.sty {
let sig = ret_ty.fn_sig(self.tcx);
let late_bound_regions = self.tcx
.collect_referenced_late_bound_regions(&sig.output());
if late_bound_regions.iter().any(|r| *r == br) {
return Some(decl.output.span());
}
_ => {}
}
None
}
@ -140,8 +137,8 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
pub(super) fn is_self_anon(&self, is_first: bool, scope_def_id: DefId) -> bool {
is_first
&& self.tcx
.opt_associated_item(scope_def_id)
.map(|i| i.method_has_self_argument) == Some(true)
.opt_associated_item(scope_def_id)
.map(|i| i.method_has_self_argument) == Some(true)
}
}

View file

@ -112,12 +112,9 @@ pub fn maybe_print_constraints_for<'a, 'gcx, 'tcx>(
}
};
match dump_region_data_to(region_rels, &region_data.constraints, &output_path) {
Ok(()) => {}
Err(e) => {
let msg = format!("io error dumping region constraints: {}", e);
tcx.sess.err(&msg)
}
if let Err(e) = dump_region_data_to(region_rels, &region_data.constraints, &output_path) {
let msg = format!("io error dumping region constraints: {}", e);
tcx.sess.err(&msg)
}
}
@ -187,12 +184,9 @@ impl<'a, 'gcx, 'tcx> dot::Labeller<'a> for ConstraintGraph<'a, 'gcx, 'tcx> {
None => bug!("no node_id found for node: {:?}", n),
};
let name = || format!("node_{}", node_id);
match dot::Id::new(name()) {
Ok(id) => id,
Err(_) => {
bug!("failed to create graphviz node identified by {}", name());
}
}
dot::Id::new(name()).unwrap_or_else(|_|
bug!("failed to create graphviz node identified by {}", name()))
}
fn node_label(&self, n: &Node) -> dot::LabelText<'_> {
match *n {
@ -204,7 +198,7 @@ impl<'a, 'gcx, 'tcx> dot::Labeller<'a> for ConstraintGraph<'a, 'gcx, 'tcx> {
match *e {
Edge::Constraint(ref c) =>
dot::LabelText::label(format!("{:?}", self.map.get(c).unwrap())),
Edge::EnclScope(..) => dot::LabelText::label("(enclosed)".to_string()),
Edge::EnclScope(..) => dot::LabelText::label("(enclosed)".to_owned()),
}
}
}

View file

@ -147,9 +147,7 @@ impl<'cx, 'gcx, 'tcx> LexicalResolver<'cx, 'gcx, 'tcx> {
fn construct_var_data(&self, tcx: TyCtxt<'_, '_, 'tcx>) -> LexicalRegionResolutions<'tcx> {
LexicalRegionResolutions {
error_region: tcx.types.re_static,
values: (0..self.num_vars())
.map(|_| VarValue::Value(tcx.types.re_empty))
.collect(),
values: IndexVec::from_elem_n(VarValue::Value(tcx.types.re_empty), self.num_vars())
}
}

View file

@ -803,6 +803,7 @@ impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> {
);
debug!("instantiate_opaque_types: ty_var={:?}", ty_var);
self.obligations.reserve(bounds.predicates.len());
for predicate in bounds.predicates {
// Change the predicate to refer to the type variable,
// which will be the concrete type instead of the opaque type.

View file

@ -443,7 +443,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
assert!(self.undo_log[snapshot.length] == OpenSnapshot);
if snapshot.length == 0 {
self.undo_log.truncate(0);
self.undo_log.clear();
} else {
(*self.undo_log)[snapshot.length] = CommitedSnapshot;
}
@ -661,11 +661,10 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
debug!("RegionConstraintCollector: add_verify({:?})", verify);
// skip no-op cases known to be satisfied
match verify.bound {
VerifyBound::AllBounds(ref bs) if bs.len() == 0 => {
if let VerifyBound::AllBounds(ref bs) = verify.bound {
if bs.len() == 0 {
return;
}
_ => {}
}
let index = self.data.verifys.len();

View file

@ -153,8 +153,8 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for FullTypeResolver<'a, 'gcx, 'tcx>
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
if !t.needs_infer() && !ty::keep_local(&t) {
t // micro-optimize -- if there is nothing in this type that this fold affects...
// ^ we need to have the `keep_local` check to un-default
// defaulted tuples.
// ^ we need to have the `keep_local` check to un-default
// defaulted tuples.
} else {
let t = self.infcx.shallow_resolve(t);
match t.sty {

View file

@ -273,11 +273,8 @@ impl<'tcx> TypeVariableTable<'tcx> {
pub fn rollback_to(&mut self, s: Snapshot<'tcx>) {
debug!("rollback_to{:?}", {
for action in self.values.actions_since_snapshot(&s.snapshot) {
match *action {
sv::UndoLog::NewElem(index) => {
debug!("inference variable _#{}t popped", index)
}
_ => { }
if let sv::UndoLog::NewElem(index) = *action {
debug!("inference variable _#{}t popped", index)
}
}
});