Skip to content

Commit 939bb32

Browse files
committed
do not propagate Err when determing causal info
In intercrate mode, if we determine that a particular `T: Trait` is unknowable, we sometimes also go and get extra causal information. An errant `?` was causing us to propagate an error found in that process out as if `T: Trait` was not unknowable but rather not provable. This led to an ICE.
1 parent 9428a3c commit 939bb32

File tree

3 files changed

+78
-19
lines changed

3 files changed

+78
-19
lines changed

src/librustc/traits/select.rs

+43-19
Original file line numberDiff line numberDiff line change
@@ -959,11 +959,21 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
959959
if self.can_use_global_caches(param_env) {
960960
let mut cache = self.tcx().evaluation_cache.hashmap.borrow_mut();
961961
if let Some(trait_ref) = self.tcx().lift_to_global(&trait_ref) {
962+
debug!(
963+
"insert_evaluation_cache(trait_ref={:?}, candidate={:?}) global",
964+
trait_ref,
965+
result,
966+
);
962967
cache.insert(trait_ref, WithDepNode::new(dep_node, result));
963968
return;
964969
}
965970
}
966971

972+
debug!(
973+
"insert_evaluation_cache(trait_ref={:?}, candidate={:?})",
974+
trait_ref,
975+
result,
976+
);
967977
self.infcx.evaluation_cache.hashmap
968978
.borrow_mut()
969979
.insert(trait_ref, WithDepNode::new(dep_node, result));
@@ -1067,25 +1077,29 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
10671077
if self.intercrate_ambiguity_causes.is_some() {
10681078
debug!("evaluate_stack: intercrate_ambiguity_causes is some");
10691079
// Heuristics: show the diagnostics when there are no candidates in crate.
1070-
let candidate_set = self.assemble_candidates(stack)?;
1071-
if !candidate_set.ambiguous && candidate_set.vec.iter().all(|c| {
1072-
!self.evaluate_candidate(stack, &c).may_apply()
1073-
}) {
1074-
let trait_ref = stack.obligation.predicate.skip_binder().trait_ref;
1075-
let self_ty = trait_ref.self_ty();
1076-
let trait_desc = trait_ref.to_string();
1077-
let self_desc = if self_ty.has_concrete_skeleton() {
1078-
Some(self_ty.to_string())
1079-
} else {
1080-
None
1081-
};
1082-
let cause = if let Conflict::Upstream = conflict {
1083-
IntercrateAmbiguityCause::UpstreamCrateUpdate { trait_desc, self_desc }
1084-
} else {
1085-
IntercrateAmbiguityCause::DownstreamCrate { trait_desc, self_desc }
1086-
};
1087-
debug!("evaluate_stack: pushing cause = {:?}", cause);
1088-
self.intercrate_ambiguity_causes.as_mut().unwrap().push(cause);
1080+
if let Ok(candidate_set) = self.assemble_candidates(stack) {
1081+
if !candidate_set.ambiguous && candidate_set.vec.iter().all(|c| {
1082+
!self.evaluate_candidate(stack, &c).may_apply()
1083+
}) {
1084+
let trait_ref = stack.obligation.predicate.skip_binder().trait_ref;
1085+
let self_ty = trait_ref.self_ty();
1086+
let trait_desc = trait_ref.to_string();
1087+
let self_desc = if self_ty.has_concrete_skeleton() {
1088+
Some(self_ty.to_string())
1089+
} else {
1090+
None
1091+
};
1092+
let cause = if let Conflict::Upstream = conflict {
1093+
IntercrateAmbiguityCause::UpstreamCrateUpdate {
1094+
trait_desc,
1095+
self_desc,
1096+
}
1097+
} else {
1098+
IntercrateAmbiguityCause::DownstreamCrate { trait_desc, self_desc }
1099+
};
1100+
debug!("evaluate_stack: pushing cause = {:?}", cause);
1101+
self.intercrate_ambiguity_causes.as_mut().unwrap().push(cause);
1102+
}
10891103
}
10901104
}
10911105
return Ok(None);
@@ -1283,12 +1297,22 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
12831297
let mut cache = tcx.selection_cache.hashmap.borrow_mut();
12841298
if let Some(trait_ref) = tcx.lift_to_global(&trait_ref) {
12851299
if let Some(candidate) = tcx.lift_to_global(&candidate) {
1300+
debug!(
1301+
"insert_candidate_cache(trait_ref={:?}, candidate={:?}) global",
1302+
trait_ref,
1303+
candidate,
1304+
);
12861305
cache.insert(trait_ref, WithDepNode::new(dep_node, candidate));
12871306
return;
12881307
}
12891308
}
12901309
}
12911310

1311+
debug!(
1312+
"insert_candidate_cache(trait_ref={:?}, candidate={:?}) local",
1313+
trait_ref,
1314+
candidate,
1315+
);
12921316
self.infcx.selection_cache.hashmap
12931317
.borrow_mut()
12941318
.insert(trait_ref, WithDepNode::new(dep_node, candidate));

src/test/ui/issue-48728.rs

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Regression test for #48728, an ICE that occurred computing
12+
// coherence "help" information.
13+
14+
#[derive(Clone)] //~ ERROR conflicting implementations of trait `std::clone::Clone`
15+
struct Node<T: ?Sized>(Box<T>);
16+
17+
impl<T: Clone + ?Sized> Clone for Node<[T]> {
18+
fn clone(&self) -> Self {
19+
Node(Box::clone(&self.0))
20+
}
21+
}
22+
23+
fn main() {}

src/test/ui/issue-48728.stderr

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
error[E0119]: conflicting implementations of trait `std::clone::Clone` for type `Node<[_]>`:
2+
--> $DIR/issue-48728.rs:14:10
3+
|
4+
LL | #[derive(Clone)] //~ ERROR conflicting implementations of trait `std::clone::Clone`
5+
| ^^^^^ conflicting implementation for `Node<[_]>`
6+
...
7+
LL | impl<T: Clone + ?Sized> Clone for Node<[T]> {
8+
| ------------------------------------------- first implementation here
9+
10+
error: aborting due to previous error
11+
12+
For more information about this error, try `rustc --explain E0119`.

0 commit comments

Comments
 (0)