Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 4c08ed5

Browse files
committedNov 23, 2017
convert the new conflicts to a soft error
1 parent 5360699 commit 4c08ed5

File tree

10 files changed

+207
-64
lines changed

10 files changed

+207
-64
lines changed
 

‎src/librustc/lint/builtin.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,12 @@ declare_lint! {
198198
"detects generic lifetime arguments in path segments with late bound lifetime parameters"
199199
}
200200

201+
declare_lint! {
202+
pub INCOHERENT_FUNDAMENTAL_IMPLS,
203+
Deny,
204+
"potentially-conflicting impls were erroneously allowed"
205+
}
206+
201207
declare_lint! {
202208
pub DEPRECATED,
203209
Warn,
@@ -254,6 +260,7 @@ impl LintPass for HardwiredLints {
254260
MISSING_FRAGMENT_SPECIFIER,
255261
PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES,
256262
LATE_BOUND_LIFETIME_ARGUMENTS,
263+
INCOHERENT_FUNDAMENTAL_IMPLS,
257264
DEPRECATED,
258265
UNUSED_UNSAFE,
259266
UNUSED_MUT

‎src/librustc/traits/coherence.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use hir::def_id::{DefId, LOCAL_CRATE};
1414
use syntax_pos::DUMMY_SP;
1515
use traits::{self, Normalized, SelectionContext, Obligation, ObligationCause, Reveal};
16+
use traits::IntercrateMode;
1617
use traits::select::IntercrateAmbiguityCause;
1718
use ty::{self, Ty, TyCtxt};
1819
use ty::subst::Subst;
@@ -42,16 +43,19 @@ pub struct OverlapResult<'tcx> {
4243
/// `ImplHeader` with those types substituted
4344
pub fn overlapping_impls<'cx, 'gcx, 'tcx>(infcx: &InferCtxt<'cx, 'gcx, 'tcx>,
4445
impl1_def_id: DefId,
45-
impl2_def_id: DefId)
46+
impl2_def_id: DefId,
47+
intercrate_mode: IntercrateMode)
4648
-> Option<OverlapResult<'tcx>>
4749
{
4850
debug!("impl_can_satisfy(\
4951
impl1_def_id={:?}, \
50-
impl2_def_id={:?})",
52+
impl2_def_id={:?},
53+
intercrate_mode={:?})",
5154
impl1_def_id,
52-
impl2_def_id);
55+
impl2_def_id,
56+
intercrate_mode);
5357

54-
let selcx = &mut SelectionContext::intercrate(infcx);
58+
let selcx = &mut SelectionContext::intercrate(infcx, intercrate_mode);
5559
overlap(selcx, impl1_def_id, impl2_def_id)
5660
}
5761

‎src/librustc/traits/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ mod structural_impls;
6060
pub mod trans;
6161
mod util;
6262

63-
#[derive(Copy, Clone, Debug)]
63+
// Whether to enable bug compatibility with issue #43355
64+
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
6465
pub enum IntercrateMode {
6566
Issue43355,
6667
Fixed

‎src/librustc/traits/select.rs

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use self::EvaluationResult::*;
1515

1616
use super::coherence::{self, Conflict};
1717
use super::DerivedObligationCause;
18+
use super::IntercrateMode;
1819
use super::project;
1920
use super::project::{normalize_with_depth, Normalized, ProjectionCacheKey};
2021
use super::{PredicateObligation, TraitObligation, ObligationCause};
@@ -87,7 +88,7 @@ pub struct SelectionContext<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> {
8788
/// other words, we consider `$0 : Bar` to be unimplemented if
8889
/// there is no type that the user could *actually name* that
8990
/// would satisfy it. This avoids crippling inference, basically.
90-
intercrate: bool,
91+
intercrate: Option<IntercrateMode>,
9192

9293
inferred_obligations: SnapshotVec<InferredObligationsSnapshotVecDelegate<'tcx>>,
9394

@@ -111,21 +112,24 @@ impl IntercrateAmbiguityCause {
111112
/// See #23980 for details.
112113
pub fn add_intercrate_ambiguity_hint<'a, 'tcx>(&self,
113114
err: &mut ::errors::DiagnosticBuilder) {
115+
err.note(&self.intercrate_ambiguity_hint());
116+
}
117+
118+
pub fn intercrate_ambiguity_hint(&self) -> String {
114119
match self {
115120
&IntercrateAmbiguityCause::DownstreamCrate { ref trait_desc, ref self_desc } => {
116121
let self_desc = if let &Some(ref ty) = self_desc {
117122
format!(" for type `{}`", ty)
118123
} else { "".to_string() };
119-
err.note(&format!("downstream crates may implement trait `{}`{}",
120-
trait_desc, self_desc));
124+
format!("downstream crates may implement trait `{}`{}", trait_desc, self_desc)
121125
}
122126
&IntercrateAmbiguityCause::UpstreamCrateUpdate { ref trait_desc, ref self_desc } => {
123127
let self_desc = if let &Some(ref ty) = self_desc {
124128
format!(" for type `{}`", ty)
125129
} else { "".to_string() };
126-
err.note(&format!("upstream crates may add new impl of trait `{}`{} \
127-
in future versions",
128-
trait_desc, self_desc));
130+
format!("upstream crates may add new impl of trait `{}`{} \
131+
in future versions",
132+
trait_desc, self_desc)
129133
}
130134
}
131135
}
@@ -417,17 +421,19 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
417421
SelectionContext {
418422
infcx,
419423
freshener: infcx.freshener(),
420-
intercrate: false,
424+
intercrate: None,
421425
inferred_obligations: SnapshotVec::new(),
422426
intercrate_ambiguity_causes: Vec::new(),
423427
}
424428
}
425429

426-
pub fn intercrate(infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>) -> SelectionContext<'cx, 'gcx, 'tcx> {
430+
pub fn intercrate(infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>,
431+
mode: IntercrateMode) -> SelectionContext<'cx, 'gcx, 'tcx> {
432+
debug!("intercrate({:?})", mode);
427433
SelectionContext {
428434
infcx,
429435
freshener: infcx.freshener(),
430-
intercrate: true,
436+
intercrate: Some(mode),
431437
inferred_obligations: SnapshotVec::new(),
432438
intercrate_ambiguity_causes: Vec::new(),
433439
}
@@ -758,7 +764,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
758764
debug!("evaluate_trait_predicate_recursively({:?})",
759765
obligation);
760766

761-
if !self.intercrate && obligation.is_global() {
767+
if !self.intercrate.is_some() && obligation.is_global() {
762768
// If a param env is consistent, global obligations do not depend on its particular
763769
// value in order to work, so we can clear out the param env and get better
764770
// caching. (If the current param env is inconsistent, we don't care what happens).
@@ -814,7 +820,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
814820
// terms of `Fn` etc, but we could probably make this more
815821
// precise still.
816822
let unbound_input_types = stack.fresh_trait_ref.input_types().any(|ty| ty.is_fresh());
817-
if unbound_input_types && self.intercrate && false {
823+
// this check was an imperfect workaround for a bug n the old
824+
// intercrate mode, it should be removed when that goes away.
825+
if unbound_input_types &&
826+
self.intercrate == Some(IntercrateMode::Issue43355)
827+
{
818828
debug!("evaluate_stack({:?}) --> unbound argument, intercrate --> ambiguous",
819829
stack.fresh_trait_ref);
820830
// Heuristics: show the diagnostics when there are no candidates in crate.
@@ -1212,9 +1222,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
12121222
stack: &TraitObligationStack<'o, 'tcx>)
12131223
-> Option<Conflict>
12141224
{
1215-
debug!("is_knowable(intercrate={})", self.intercrate);
1225+
debug!("is_knowable(intercrate={:?})", self.intercrate);
12161226

1217-
if !self.intercrate {
1227+
if !self.intercrate.is_some() {
12181228
return None;
12191229
}
12201230

@@ -1226,7 +1236,14 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
12261236
// bound regions
12271237
let trait_ref = predicate.skip_binder().trait_ref;
12281238

1229-
coherence::trait_ref_is_knowable(self.tcx(), trait_ref)
1239+
let result = coherence::trait_ref_is_knowable(self.tcx(), trait_ref);
1240+
if let (Some(Conflict::Downstream { used_to_be_broken: true }),
1241+
Some(IntercrateMode::Issue43355)) = (result, self.intercrate) {
1242+
debug!("is_knowable: IGNORING conflict to be bug-compatible with #43355");
1243+
None
1244+
} else {
1245+
result
1246+
}
12301247
}
12311248

12321249
/// Returns true if the global caches can be used.
@@ -1251,7 +1268,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
12511268
// the master cache. Since coherence executes pretty quickly,
12521269
// it's not worth going to more trouble to increase the
12531270
// hit-rate I don't think.
1254-
if self.intercrate {
1271+
if self.intercrate.is_some() {
12551272
return false;
12561273
}
12571274

‎src/librustc/traits/specialize/mod.rs

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ use ty::{self, TyCtxt, TypeFoldable};
3030
use syntax_pos::DUMMY_SP;
3131
use std::rc::Rc;
3232

33+
use lint;
34+
3335
pub mod specialization_graph;
3436

3537
/// Information pertinent to an overlapping impl error.
@@ -314,16 +316,33 @@ pub(super) fn specialization_graph_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx
314316
// This is where impl overlap checking happens:
315317
let insert_result = sg.insert(tcx, impl_def_id);
316318
// Report error if there was one.
317-
if let Err(overlap) = insert_result {
318-
let mut err = struct_span_err!(tcx.sess,
319-
tcx.span_of_impl(impl_def_id).unwrap(),
320-
E0119,
321-
"conflicting implementations of trait `{}`{}:",
322-
overlap.trait_desc,
323-
overlap.self_desc.clone().map_or(String::new(),
324-
|ty| {
325-
format!(" for type `{}`", ty)
326-
}));
319+
let (overlap, used_to_be_allowed) = match insert_result {
320+
Err(overlap) => (Some(overlap), false),
321+
Ok(opt_overlap) => (opt_overlap, true)
322+
};
323+
324+
if let Some(overlap) = overlap {
325+
let msg = format!("conflicting implementations of trait `{}`{}:{}",
326+
overlap.trait_desc,
327+
overlap.self_desc.clone().map_or(
328+
String::new(), |ty| {
329+
format!(" for type `{}`", ty)
330+
}),
331+
if used_to_be_allowed { " (E0119)" } else { "" }
332+
);
333+
let mut err = if used_to_be_allowed {
334+
tcx.struct_span_lint_node(
335+
lint::builtin::INCOHERENT_FUNDAMENTAL_IMPLS,
336+
tcx.hir.as_local_node_id(impl_def_id).unwrap(),
337+
tcx.span_of_impl(impl_def_id).unwrap(),
338+
&msg)
339+
} else {
340+
struct_span_err!(tcx.sess,
341+
tcx.span_of_impl(impl_def_id).unwrap(),
342+
E0119,
343+
"{}",
344+
msg)
345+
};
327346

328347
match tcx.span_of_impl(overlap.with_impl) {
329348
Ok(span) => {

‎src/librustc/traits/specialize/specialization_graph.rs

Lines changed: 45 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ struct Children {
6868
/// The result of attempting to insert an impl into a group of children.
6969
enum Inserted {
7070
/// The impl was inserted as a new child in this group of children.
71-
BecameNewSibling,
71+
BecameNewSibling(Option<OverlapError>),
7272

7373
/// The impl replaced an existing impl that specializes it.
7474
Replaced(DefId),
@@ -105,17 +105,39 @@ impl<'a, 'gcx, 'tcx> Children {
105105
simplified_self: Option<SimplifiedType>)
106106
-> Result<Inserted, OverlapError>
107107
{
108+
let mut last_lint = None;
109+
108110
for slot in match simplified_self {
109111
Some(sty) => self.filtered_mut(sty),
110112
None => self.iter_mut(),
111113
} {
112114
let possible_sibling = *slot;
113115

116+
let overlap_error = |overlap: traits::coherence::OverlapResult| {
117+
// overlap, but no specialization; error out
118+
let trait_ref = overlap.impl_header.trait_ref.unwrap();
119+
let self_ty = trait_ref.self_ty();
120+
OverlapError {
121+
with_impl: possible_sibling,
122+
trait_desc: trait_ref.to_string(),
123+
// only report the Self type if it has at least
124+
// some outer concrete shell; otherwise, it's
125+
// not adding much information.
126+
self_desc: if self_ty.has_concrete_skeleton() {
127+
Some(self_ty.to_string())
128+
} else {
129+
None
130+
},
131+
intercrate_ambiguity_causes: overlap.intercrate_ambiguity_causes,
132+
}
133+
};
134+
114135
let tcx = tcx.global_tcx();
115136
let (le, ge) = tcx.infer_ctxt().enter(|infcx| {
116137
let overlap = traits::overlapping_impls(&infcx,
117138
possible_sibling,
118-
impl_def_id);
139+
impl_def_id,
140+
traits::IntercrateMode::Issue43355);
119141
if let Some(overlap) = overlap {
120142
if tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling) {
121143
return Ok((false, false));
@@ -125,22 +147,7 @@ impl<'a, 'gcx, 'tcx> Children {
125147
let ge = tcx.specializes((possible_sibling, impl_def_id));
126148

127149
if le == ge {
128-
// overlap, but no specialization; error out
129-
let trait_ref = overlap.impl_header.trait_ref.unwrap();
130-
let self_ty = trait_ref.self_ty();
131-
Err(OverlapError {
132-
with_impl: possible_sibling,
133-
trait_desc: trait_ref.to_string(),
134-
// only report the Self type if it has at least
135-
// some outer concrete shell; otherwise, it's
136-
// not adding much information.
137-
self_desc: if self_ty.has_concrete_skeleton() {
138-
Some(self_ty.to_string())
139-
} else {
140-
None
141-
},
142-
intercrate_ambiguity_causes: overlap.intercrate_ambiguity_causes,
143-
})
150+
Err(overlap_error(overlap))
144151
} else {
145152
Ok((le, ge))
146153
}
@@ -163,14 +170,27 @@ impl<'a, 'gcx, 'tcx> Children {
163170
*slot = impl_def_id;
164171
return Ok(Inserted::Replaced(possible_sibling));
165172
} else {
173+
if !tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling) {
174+
tcx.infer_ctxt().enter(|infcx| {
175+
if let Some(overlap) = traits::overlapping_impls(
176+
&infcx,
177+
possible_sibling,
178+
impl_def_id,
179+
traits::IntercrateMode::Fixed)
180+
{
181+
last_lint = Some(overlap_error(overlap));
182+
}
183+
});
184+
}
185+
166186
// no overlap (error bailed already via ?)
167187
}
168188
}
169189

170190
// no overlap with any potential siblings, so add as a new sibling
171191
debug!("placing as new sibling");
172192
self.insert_blindly(tcx, impl_def_id);
173-
Ok(Inserted::BecameNewSibling)
193+
Ok(Inserted::BecameNewSibling(last_lint))
174194
}
175195

176196
fn iter_mut(&'a mut self) -> Box<Iterator<Item = &'a mut DefId> + 'a> {
@@ -199,7 +219,7 @@ impl<'a, 'gcx, 'tcx> Graph {
199219
pub fn insert(&mut self,
200220
tcx: TyCtxt<'a, 'gcx, 'tcx>,
201221
impl_def_id: DefId)
202-
-> Result<(), OverlapError> {
222+
-> Result<Option<OverlapError>, OverlapError> {
203223
assert!(impl_def_id.is_local());
204224

205225
let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
@@ -220,10 +240,11 @@ impl<'a, 'gcx, 'tcx> Graph {
220240
self.parent.insert(impl_def_id, trait_def_id);
221241
self.children.entry(trait_def_id).or_insert(Children::new())
222242
.insert_blindly(tcx, impl_def_id);
223-
return Ok(());
243+
return Ok(None);
224244
}
225245

226246
let mut parent = trait_def_id;
247+
let mut last_lint = None;
227248
let simplified = fast_reject::simplify_type(tcx, trait_ref.self_ty(), false);
228249

229250
// Descend the specialization tree, where `parent` is the current parent node
@@ -234,7 +255,8 @@ impl<'a, 'gcx, 'tcx> Graph {
234255
.insert(tcx, impl_def_id, simplified)?;
235256

236257
match insert_result {
237-
BecameNewSibling => {
258+
BecameNewSibling(opt_lint) => {
259+
last_lint = opt_lint;
238260
break;
239261
}
240262
Replaced(new_child) => {
@@ -251,7 +273,7 @@ impl<'a, 'gcx, 'tcx> Graph {
251273
}
252274

253275
self.parent.insert(impl_def_id, parent);
254-
Ok(())
276+
Ok(last_lint)
255277
}
256278

257279
/// Insert cached metadata mapping from a child impl back to its parent.

‎src/librustc_lint/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,10 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
243243
id: LintId::of(LATE_BOUND_LIFETIME_ARGUMENTS),
244244
reference: "issue #42868 <https://github.com/rust-lang/rust/issues/42868>",
245245
},
246+
FutureIncompatibleInfo {
247+
id: LintId::of(INCOHERENT_FUNDAMENTAL_IMPLS),
248+
reference: "issue #46205 <https://github.com/rust-lang/rust/issues/46205>",
249+
},
246250
]);
247251

248252
// Register renamed and removed lints

‎src/librustc_typeck/coherence/inherent_impls_overlap.rs

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@ use namespace::Namespace;
1212
use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
1313
use rustc::hir;
1414
use rustc::hir::itemlikevisit::ItemLikeVisitor;
15-
use rustc::traits;
15+
use rustc::traits::{self, IntercrateMode};
1616
use rustc::ty::TyCtxt;
1717

18+
use lint;
19+
1820
pub fn crate_inherent_impls_overlap_check<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
1921
crate_num: CrateNum) {
2022
assert_eq!(crate_num, LOCAL_CRATE);
@@ -28,7 +30,8 @@ struct InherentOverlapChecker<'a, 'tcx: 'a> {
2830

2931
impl<'a, 'tcx> InherentOverlapChecker<'a, 'tcx> {
3032
fn check_for_common_items_in_impls(&self, impl1: DefId, impl2: DefId,
31-
overlap: traits::OverlapResult) {
33+
overlap: traits::OverlapResult,
34+
used_to_be_allowed: bool) {
3235

3336
let name_and_namespace = |def_id| {
3437
let item = self.tcx.associated_item(def_id);
@@ -43,11 +46,21 @@ impl<'a, 'tcx> InherentOverlapChecker<'a, 'tcx> {
4346

4447
for &item2 in &impl_items2[..] {
4548
if (name, namespace) == name_and_namespace(item2) {
46-
let mut err = struct_span_err!(self.tcx.sess,
47-
self.tcx.span_of_impl(item1).unwrap(),
48-
E0592,
49-
"duplicate definitions with name `{}`",
50-
name);
49+
let node_id = self.tcx.hir.as_local_node_id(impl1);
50+
let mut err = if used_to_be_allowed && node_id.is_some() {
51+
self.tcx.struct_span_lint_node(
52+
lint::builtin::INCOHERENT_FUNDAMENTAL_IMPLS,
53+
node_id.unwrap(),
54+
self.tcx.span_of_impl(item1).unwrap(),
55+
&format!("duplicate definitions with name `{}` (E0592)", name)
56+
)
57+
} else {
58+
struct_span_err!(self.tcx.sess,
59+
self.tcx.span_of_impl(item1).unwrap(),
60+
E0592,
61+
"duplicate definitions with name `{}`",
62+
name)
63+
};
5164

5265
err.span_label(self.tcx.span_of_impl(item1).unwrap(),
5366
format!("duplicate definitions for `{}`", name));
@@ -69,12 +82,30 @@ impl<'a, 'tcx> InherentOverlapChecker<'a, 'tcx> {
6982

7083
for (i, &impl1_def_id) in impls.iter().enumerate() {
7184
for &impl2_def_id in &impls[(i + 1)..] {
72-
self.tcx.infer_ctxt().enter(|infcx| {
85+
let used_to_be_allowed = self.tcx.infer_ctxt().enter(|infcx| {
7386
if let Some(overlap) =
74-
traits::overlapping_impls(&infcx, impl1_def_id, impl2_def_id) {
75-
self.check_for_common_items_in_impls(impl1_def_id, impl2_def_id, overlap)
87+
traits::overlapping_impls(&infcx, impl1_def_id, impl2_def_id,
88+
IntercrateMode::Issue43355)
89+
{
90+
self.check_for_common_items_in_impls(
91+
impl1_def_id, impl2_def_id, overlap, false);
92+
false
93+
} else {
94+
true
7695
}
7796
});
97+
98+
if used_to_be_allowed {
99+
self.tcx.infer_ctxt().enter(|infcx| {
100+
if let Some(overlap) =
101+
traits::overlapping_impls(&infcx, impl1_def_id, impl2_def_id,
102+
IntercrateMode::Fixed)
103+
{
104+
self.check_for_common_items_in_impls(
105+
impl1_def_id, impl2_def_id, overlap, true);
106+
}
107+
});
108+
}
78109
}
79110
}
80111
}
@@ -100,4 +131,3 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentOverlapChecker<'a, 'tcx> {
100131
fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
101132
}
102133
}
103-

‎src/test/compile-fail/issue-43355.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ impl<X, T> Trait1<X> for T where T: Trait2<X> {
2222

2323
impl<X> Trait1<Box<X>> for A {
2424
//~^ ERROR conflicting implementations of trait
25+
//~| hard error
2526
//~| downstream crates may implement trait `Trait2<std::boxed::Box<_>>` for type `A`
2627
type Output = i32;
2728
}

‎src/test/run-pass/issue-43355.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Copyright 2017 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+
// Check that the code for issue #43355 can run without an ICE, please remove
12+
// this test when it becomes an hard error.
13+
14+
#![allow(incoherent_fundamental_impls)]
15+
16+
pub trait Trait1<X> {
17+
type Output;
18+
}
19+
pub trait Trait2<X> {}
20+
21+
impl<X, T> Trait1<X> for T where T: Trait2<X> {
22+
type Output = ();
23+
}
24+
impl<X> Trait1<Box<X>> for A {
25+
type Output = i32;
26+
}
27+
28+
pub struct A;
29+
30+
fn f<X, T: Trait1<Box<X>>>() {
31+
println!("k: {}", ::std::mem::size_of::<<T as Trait1<Box<X>>>::Output>());
32+
}
33+
34+
pub fn g<X, T: Trait2<Box<X>>>() {
35+
f::<X, T>();
36+
}
37+
38+
fn main() {}

0 commit comments

Comments
 (0)
Please sign in to comment.