Skip to content

Commit 6f8d831

Browse files
committed
Auto merge of #22851 - FlaPer87:oibit-send-and-friends, r=nikomatsakis
Fixes #22828 Fixes #22629 r? @nikomatsakis
2 parents 8519e78 + b7f9d07 commit 6f8d831

File tree

4 files changed

+114
-63
lines changed

4 files changed

+114
-63
lines changed

src/librustc/middle/traits/select.rs

+64-62
Original file line numberDiff line numberDiff line change
@@ -1716,6 +1716,60 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
17161716
}
17171717
}
17181718

1719+
fn collect_predicates_for_types(&mut self,
1720+
obligation: &TraitObligation<'tcx>,
1721+
trait_def_id: ast::DefId,
1722+
types: Vec<Ty<'tcx>>) -> Vec<PredicateObligation<'tcx>> {
1723+
1724+
let derived_cause = match self.tcx().lang_items.to_builtin_kind(trait_def_id) {
1725+
Some(_) => {
1726+
self.derived_cause(obligation, BuiltinDerivedObligation)
1727+
},
1728+
None => {
1729+
self.derived_cause(obligation, ImplDerivedObligation)
1730+
}
1731+
};
1732+
1733+
let normalized = project::normalize_with_depth(self, obligation.cause.clone(),
1734+
obligation.recursion_depth + 1,
1735+
&types);
1736+
1737+
let obligations = normalized.value.iter().map(|&nested_ty| {
1738+
// the obligation might be higher-ranked, e.g. for<'a> &'a
1739+
// int : Copy. In that case, we will wind up with
1740+
// late-bound regions in the `nested` vector. So for each
1741+
// one we instantiate to a skolemized region, do our work
1742+
// to produce something like `&'0 int : Copy`, and then
1743+
// re-bind it. This is a bit of busy-work but preserves
1744+
// the invariant that we only manipulate free regions, not
1745+
// bound ones.
1746+
self.infcx.try(|snapshot| {
1747+
let (skol_ty, skol_map) =
1748+
self.infcx().skolemize_late_bound_regions(&ty::Binder(nested_ty), snapshot);
1749+
let skol_predicate =
1750+
util::predicate_for_trait_def(
1751+
self.tcx(),
1752+
derived_cause.clone(),
1753+
trait_def_id,
1754+
obligation.recursion_depth + 1,
1755+
skol_ty);
1756+
match skol_predicate {
1757+
Ok(skol_predicate) => Ok(self.infcx().plug_leaks(skol_map, snapshot,
1758+
&skol_predicate)),
1759+
Err(ErrorReported) => Err(ErrorReported)
1760+
}
1761+
})
1762+
}).collect::<Result<Vec<PredicateObligation<'tcx>>, _>>();
1763+
1764+
match obligations {
1765+
Ok(mut obls) => {
1766+
obls.push_all(normalized.obligations.as_slice());
1767+
obls
1768+
},
1769+
Err(ErrorReported) => Vec::new()
1770+
}
1771+
}
1772+
17191773
///////////////////////////////////////////////////////////////////////////
17201774
// CONFIRMATION
17211775
//
@@ -1854,38 +1908,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
18541908
nested: Vec<Ty<'tcx>>)
18551909
-> VtableBuiltinData<PredicateObligation<'tcx>>
18561910
{
1857-
let derived_cause = self.derived_cause(obligation, BuiltinDerivedObligation);
1858-
let obligations = nested.iter().map(|&bound_ty| {
1859-
// the obligation might be higher-ranked, e.g. for<'a> &'a
1860-
// int : Copy. In that case, we will wind up with
1861-
// late-bound regions in the `nested` vector. So for each
1862-
// one we instantiate to a skolemized region, do our work
1863-
// to produce something like `&'0 int : Copy`, and then
1864-
// re-bind it. This is a bit of busy-work but preserves
1865-
// the invariant that we only manipulate free regions, not
1866-
// bound ones.
1867-
self.infcx.try(|snapshot| {
1868-
let (skol_ty, skol_map) =
1869-
self.infcx().skolemize_late_bound_regions(&ty::Binder(bound_ty), snapshot);
1870-
let skol_predicate =
1871-
util::predicate_for_builtin_bound(
1872-
self.tcx(),
1873-
derived_cause.clone(),
1874-
bound,
1875-
obligation.recursion_depth + 1,
1876-
skol_ty);
1877-
match skol_predicate {
1878-
Ok(skol_predicate) => Ok(self.infcx().plug_leaks(skol_map, snapshot,
1879-
&skol_predicate)),
1880-
Err(ErrorReported) => Err(ErrorReported)
1881-
}
1882-
})
1883-
}).collect::<Result<_, _>>();
1884-
let obligations = match obligations {
1885-
Ok(o) => o,
1886-
Err(ErrorReported) => Vec::new(),
1911+
let trait_def = match self.tcx().lang_items.from_builtin_kind(bound) {
1912+
Ok(def_id) => def_id,
1913+
Err(_) => {
1914+
self.tcx().sess.bug("builtin trait definition not found");
1915+
}
18871916
};
18881917

1918+
let obligations = self.collect_predicates_for_types(obligation, trait_def, nested);
1919+
18891920
let obligations = VecPerParamSpace::new(obligations, Vec::new(), Vec::new());
18901921

18911922
debug!("vtable_builtin_data: obligations={}",
@@ -1928,39 +1959,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
19281959
nested: Vec<Ty<'tcx>>)
19291960
-> VtableDefaultImplData<PredicateObligation<'tcx>>
19301961
{
1931-
let derived_cause = self.derived_cause(obligation, ImplDerivedObligation);
19321962

1933-
let obligations = nested.iter().map(|&nested_ty| {
1934-
// the obligation might be higher-ranked, e.g. for<'a> &'a
1935-
// int : Copy. In that case, we will wind up with
1936-
// late-bound regions in the `nested` vector. So for each
1937-
// one we instantiate to a skolemized region, do our work
1938-
// to produce something like `&'0 int : Copy`, and then
1939-
// re-bind it. This is a bit of busy-work but preserves
1940-
// the invariant that we only manipulate free regions, not
1941-
// bound ones.
1942-
self.infcx.try(|snapshot| {
1943-
let (skol_ty, skol_map) =
1944-
self.infcx().skolemize_late_bound_regions(&ty::Binder(nested_ty), snapshot);
1945-
let skol_predicate =
1946-
util::predicate_for_default_trait_impl(
1947-
self.tcx(),
1948-
derived_cause.clone(),
1949-
trait_def_id,
1950-
obligation.recursion_depth + 1,
1951-
skol_ty);
1952-
match skol_predicate {
1953-
Ok(skol_predicate) => Ok(self.infcx().plug_leaks(skol_map, snapshot,
1954-
&skol_predicate)),
1955-
Err(ErrorReported) => Err(ErrorReported)
1956-
}
1957-
})
1958-
}).collect::<Result<_, _>>();
1959-
1960-
let mut obligations = match obligations {
1961-
Ok(o) => o,
1962-
Err(ErrorReported) => Vec::new()
1963-
};
1963+
let mut obligations = self.collect_predicates_for_types(obligation,
1964+
trait_def_id,
1965+
nested);
19641966

19651967
let _: Result<(),()> = self.infcx.try(|snapshot| {
19661968
let (_, skol_map) =

src/librustc/middle/traits/util.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,7 @@ pub fn predicate_for_trait_ref<'tcx>(
337337
})
338338
}
339339

340-
pub fn predicate_for_default_trait_impl<'tcx>(
340+
pub fn predicate_for_trait_def<'tcx>(
341341
tcx: &ty::ctxt<'tcx>,
342342
cause: ObligationCause<'tcx>,
343343
trait_def_id: ast::DefId,

src/test/run-pass/issue-22629.rs

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
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+
// Test transitive analysis for associated types. Collected types
12+
// should be normalized and new obligations generated.
13+
14+
use std::borrow::{ToOwned, Cow};
15+
16+
fn assert_send<T: Send>(_: T) {}
17+
18+
fn main() {
19+
assert_send(Cow::Borrowed("foo"));
20+
}

src/test/run-pass/issue-22828.rs

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
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+
// Test transitive analysis for associated types. Collected types
12+
// should be normalized and new obligations generated.
13+
14+
trait Foo {
15+
type A;
16+
fn foo(&self) {}
17+
}
18+
19+
impl Foo for usize {
20+
type A = usize;
21+
}
22+
23+
struct Bar<T: Foo> { inner: T::A }
24+
25+
fn is_send<T: Send>() {}
26+
27+
fn main() {
28+
is_send::<Bar<usize>>();
29+
}

0 commit comments

Comments
 (0)