Skip to content

Commit 4eb7a33

Browse files
author
Ariel Ben-Yehuda
authored
Rollup merge of rust-lang#40268 - Mark-Simulacrum:normalization-followup, r=arielb1
Fix normalization error Follows rust-lang#40163. I don't know whether this is good, but seems logical. [This block of code](https://github.com/rust-lang/rust/blob/ba07bd5d23aced6d4baa5696213b11ca832c1a5d/src/librustc_typeck/check/mod.rs#L2110-L2138) doesn't contain a call to `normalize_associated_types_in`, while [this](https://github.com/rust-lang/rust/blob/master/src/librustc_typeck/check/mod.rs#L2027-L2028) block does, and is nearly identical. Ideally these two blocks should be unified into one, but since the change doesn't seem trivial and I'm unsure if this patch will be accepted it hasn't been done yet. r? @arielb1
2 parents 5694ac9 + 403ae37 commit 4eb7a33

File tree

1 file changed

+54
-85
lines changed
  • src/librustc_typeck/check

1 file changed

+54
-85
lines changed

src/librustc_typeck/check/mod.rs

+54-85
Original file line numberDiff line numberDiff line change
@@ -1935,10 +1935,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
19351935
// We must collect the defaults *before* we do any unification. Because we have
19361936
// directly attached defaults to the type variables any unification that occurs
19371937
// will erase defaults causing conflicting defaults to be completely ignored.
1938-
let default_map: FxHashMap<_, _> =
1938+
let default_map: FxHashMap<Ty<'tcx>, _> =
19391939
unsolved_variables
19401940
.iter()
1941-
.filter_map(|t| self.default(t).map(|d| (t, d)))
1941+
.filter_map(|t| self.default(t).map(|d| (*t, d)))
19421942
.collect();
19431943

19441944
let mut unbound_tyvars = FxHashSet();
@@ -2007,37 +2007,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
20072007
// we will rollback the inference context to its prior state so we can probe
20082008
// for conflicts and correctly report them.
20092009

2010-
20112010
let _ = self.commit_if_ok(|_: &infer::CombinedSnapshot| {
2012-
for ty in &unbound_tyvars {
2013-
if self.type_var_diverges(ty) {
2014-
self.demand_eqtype(syntax_pos::DUMMY_SP, *ty,
2015-
self.tcx.mk_diverging_default());
2016-
} else {
2017-
match self.type_is_unconstrained_numeric(ty) {
2018-
UnconstrainedInt => {
2019-
self.demand_eqtype(syntax_pos::DUMMY_SP, *ty, self.tcx.types.i32)
2020-
},
2021-
UnconstrainedFloat => {
2022-
self.demand_eqtype(syntax_pos::DUMMY_SP, *ty, self.tcx.types.f64)
2023-
}
2024-
Neither => {
2025-
if let Some(default) = default_map.get(ty) {
2026-
let default = default.clone();
2027-
let default_ty = self.normalize_associated_types_in(
2028-
default.origin_span, &default.ty);
2029-
match self.eq_types(false,
2030-
&self.misc(default.origin_span),
2031-
ty,
2032-
default_ty) {
2033-
Ok(ok) => self.register_infer_ok_obligations(ok),
2034-
Err(_) => conflicts.push((*ty, default)),
2035-
}
2036-
}
2037-
}
2038-
}
2039-
}
2040-
}
2011+
conflicts.extend(
2012+
self.apply_defaults_and_return_conflicts(&unbound_tyvars, &default_map, None)
2013+
);
20412014

20422015
// If there are conflicts we rollback, otherwise commit
20432016
if conflicts.len() > 0 {
@@ -2047,37 +2020,41 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
20472020
}
20482021
});
20492022

2050-
if conflicts.len() > 0 {
2051-
// Loop through each conflicting default, figuring out the default that caused
2052-
// a unification failure and then report an error for each.
2053-
for (conflict, default) in conflicts {
2054-
let conflicting_default =
2055-
self.find_conflicting_default(&unbound_tyvars, &default_map, conflict)
2056-
.unwrap_or(type_variable::Default {
2057-
ty: self.next_ty_var(
2058-
TypeVariableOrigin::MiscVariable(syntax_pos::DUMMY_SP)),
2059-
origin_span: syntax_pos::DUMMY_SP,
2060-
// what do I put here?
2061-
def_id: self.tcx.hir.local_def_id(ast::CRATE_NODE_ID)
2062-
});
2063-
2064-
// This is to ensure that we elimnate any non-determinism from the error
2065-
// reporting by fixing an order, it doesn't matter what order we choose
2066-
// just that it is consistent.
2067-
let (first_default, second_default) =
2068-
if default.def_id < conflicting_default.def_id {
2069-
(default, conflicting_default)
2070-
} else {
2071-
(conflicting_default, default)
2072-
};
2023+
// Loop through each conflicting default, figuring out the default that caused
2024+
// a unification failure and then report an error for each.
2025+
for (conflict, default) in conflicts {
2026+
let conflicting_default =
2027+
self.apply_defaults_and_return_conflicts(
2028+
&unbound_tyvars,
2029+
&default_map,
2030+
Some(conflict)
2031+
)
2032+
.last()
2033+
.map(|(_, tv)| tv)
2034+
.unwrap_or(type_variable::Default {
2035+
ty: self.next_ty_var(
2036+
TypeVariableOrigin::MiscVariable(syntax_pos::DUMMY_SP)),
2037+
origin_span: syntax_pos::DUMMY_SP,
2038+
// what do I put here?
2039+
def_id: self.tcx.hir.local_def_id(ast::CRATE_NODE_ID)
2040+
});
2041+
2042+
// This is to ensure that we elimnate any non-determinism from the error
2043+
// reporting by fixing an order, it doesn't matter what order we choose
2044+
// just that it is consistent.
2045+
let (first_default, second_default) =
2046+
if default.def_id < conflicting_default.def_id {
2047+
(default, conflicting_default)
2048+
} else {
2049+
(conflicting_default, default)
2050+
};
20732051

20742052

2075-
self.report_conflicting_default_types(
2076-
first_default.origin_span,
2077-
self.body_id,
2078-
first_default,
2079-
second_default)
2080-
}
2053+
self.report_conflicting_default_types(
2054+
first_default.origin_span,
2055+
self.body_id,
2056+
first_default,
2057+
second_default)
20812058
}
20822059
}
20832060

@@ -2088,56 +2065,48 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
20882065
// apply the default that caused conflict first to a local version of the type variable
20892066
// table then apply defaults until we find a conflict. That default must be the one
20902067
// that caused conflict earlier.
2091-
fn find_conflicting_default(&self,
2092-
unbound_vars: &FxHashSet<Ty<'tcx>>,
2093-
default_map: &FxHashMap<&Ty<'tcx>, type_variable::Default<'tcx>>,
2094-
conflict: Ty<'tcx>)
2095-
-> Option<type_variable::Default<'tcx>> {
2068+
fn apply_defaults_and_return_conflicts<'b>(
2069+
&'b self,
2070+
unbound_vars: &'b FxHashSet<Ty<'tcx>>,
2071+
default_map: &'b FxHashMap<Ty<'tcx>, type_variable::Default<'tcx>>,
2072+
conflict: Option<Ty<'tcx>>,
2073+
) -> impl Iterator<Item=(Ty<'tcx>, type_variable::Default<'tcx>)> + 'b {
20962074
use rustc::ty::error::UnconstrainedNumeric::Neither;
20972075
use rustc::ty::error::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat};
20982076

2099-
// Ensure that we apply the conflicting default first
2100-
let mut unbound_tyvars = Vec::with_capacity(unbound_vars.len() + 1);
2101-
unbound_tyvars.push(conflict);
2102-
unbound_tyvars.extend(unbound_vars.iter());
2103-
2104-
let mut result = None;
2105-
// We run the same code as above applying defaults in order, this time when
2106-
// we find the conflict we just return it for error reporting above.
2107-
2108-
// We also run this inside snapshot that never commits so we can do error
2109-
// reporting for more then one conflict.
2110-
for ty in &unbound_tyvars {
2077+
conflict.into_iter().chain(unbound_vars.iter().cloned()).flat_map(move |ty| {
21112078
if self.type_var_diverges(ty) {
2112-
self.demand_eqtype(syntax_pos::DUMMY_SP, *ty,
2079+
self.demand_eqtype(syntax_pos::DUMMY_SP, ty,
21132080
self.tcx.mk_diverging_default());
21142081
} else {
21152082
match self.type_is_unconstrained_numeric(ty) {
21162083
UnconstrainedInt => {
2117-
self.demand_eqtype(syntax_pos::DUMMY_SP, *ty, self.tcx.types.i32)
2084+
self.demand_eqtype(syntax_pos::DUMMY_SP, ty, self.tcx.types.i32)
21182085
},
21192086
UnconstrainedFloat => {
2120-
self.demand_eqtype(syntax_pos::DUMMY_SP, *ty, self.tcx.types.f64)
2087+
self.demand_eqtype(syntax_pos::DUMMY_SP, ty, self.tcx.types.f64)
21212088
},
21222089
Neither => {
21232090
if let Some(default) = default_map.get(ty) {
21242091
let default = default.clone();
2092+
let default_ty = self.normalize_associated_types_in(
2093+
default.origin_span, &default.ty);
21252094
match self.eq_types(false,
21262095
&self.misc(default.origin_span),
21272096
ty,
2128-
default.ty) {
2097+
default_ty) {
21292098
Ok(ok) => self.register_infer_ok_obligations(ok),
21302099
Err(_) => {
2131-
result = Some(default);
2100+
return Some((ty, default));
21322101
}
21332102
}
21342103
}
21352104
}
21362105
}
21372106
}
2138-
}
21392107

2140-
return result;
2108+
None
2109+
})
21412110
}
21422111

21432112
fn select_all_obligations_or_error(&self) {

0 commit comments

Comments
 (0)