Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
f7d745f
tag/niche terminology cleanup
RalfJung May 23, 2020
7a6d03c
miri errors: rename InvalidDiscriminant -> InvalidTag
RalfJung May 30, 2020
e9b67d2
Fix link error with #[thread_local] introduced by #71192
Amanieu Jun 6, 2020
5837518
`-Zunpretty=everybody_loops` only works after expansion
ecstatic-morse Jun 7, 2020
d684855
Helper method for whether `ast::Ty` contains `impl Trait`
ecstatic-morse Jun 7, 2020
b5fdbbe
Use correct names for things in `ReplaceBodyWithLoops`
ecstatic-morse Jun 7, 2020
d8c99f3
Preserve expressions that get a `DefId`
ecstatic-morse Jun 7, 2020
1a30042
Remove unnecessary `opt_local_def_id_to_hir_id`
ecstatic-morse Jun 7, 2020
e319f20
Add `rustdoc` tests from #72088
ecstatic-morse Jun 7, 2020
c920ae9
Correctly handle binders inside trait predicates
matthewjasper May 30, 2020
d14ee0b
Consider fewer predicates for projection candidates
matthewjasper May 30, 2020
fb16ee7
Check associated type satisfy their bounds
matthewjasper May 30, 2020
373c735
Don't set STILL_FURTHER_SPECIALIZABLE for regions/bound variables
matthewjasper Jun 10, 2020
2af53e9
Add -O compile flag to test
Amanieu Jun 10, 2020
83c5028
Move bounds on associated types to the type
matthewjasper Jun 11, 2020
f0d2e78
add raw_ref macros
RalfJung Jun 12, 2020
01e29c7
Don't run test on emscripten which doesn't have threads
Amanieu Jun 13, 2020
e785472
Explain what the substs we're creating are
matthewjasper Jun 13, 2020
0687b78
Speed up bootstrap a little.
ehuss Jun 13, 2020
d5ea0e9
Report error when casting an C-like enum implementing Drop
oddg May 15, 2020
a40156e
UI test for deprecation warning of casting enum implementing Drop
oddg Jun 14, 2020
607e851
Switch bootstrap metadata to --no-deps.
ehuss Jun 14, 2020
c2b920f
Show suite paths (`src/test/ui/...`) in help output.
ehuss Jun 14, 2020
f17fd7b
Add some doc comments regarding PathSet.
ehuss Jun 15, 2020
d6156e8
Change how compiler-builtins gets many CGUs
alexcrichton Jun 8, 2020
e857696
Tweak "non-primitive cast" error
estebank Jun 15, 2020
81c9094
Suggest substituting `'static` lifetime in impl/dyn `Trait + 'static`…
estebank May 29, 2020
4e90f17
When `'static` is explicit, suggest constraining argument with it
estebank May 30, 2020
921f35f
Reduce verbosity of suggestion message and mention lifetime in label
estebank May 30, 2020
e755889
Move overlapping span to a note
estebank May 30, 2020
bc15790
Tweak output for overlapping required/captured spans
estebank May 30, 2020
539e978
Tweak wording and add error code
estebank May 30, 2020
31ea589
review comments: wording
estebank Jun 1, 2020
10d9bf1
Use note for requirement source span
estebank Jun 2, 2020
34d8692
Register new eror code
estebank Jun 2, 2020
e31367d
small tweaks
estebank Jun 2, 2020
f7a1f97
Change E0758 to E0759 to avoid conflict with #72912
estebank Jun 3, 2020
bfe1434
fix rebase
estebank Jun 15, 2020
b5809b0
Update src/librustc_typeck/check/cast.rs
nikomatsakis Jun 15, 2020
10c8d2a
add FIXME to EnumTagInfo
RalfJung Jun 15, 2020
f3dfe80
Adjust error message
oddg Jun 16, 2020
0265e4e
add tracking issue
RalfJung Jun 16, 2020
b03de50
Rollup merge of #72279 - RalfJung:raw-ref-macros, r=nikomatsakis
Manishearth Jun 16, 2020
259b3f6
Rollup merge of #72331 - oddg:forbid-cast-of-cenum-implementing-drop,…
Manishearth Jun 16, 2020
dd83a9b
Rollup merge of #72497 - RalfJung:tag-term, r=oli-obk
Manishearth Jun 16, 2020
0daff91
Rollup merge of #72788 - matthewjasper:projection-bound-validation, r…
Manishearth Jun 16, 2020
49cbe7a
Rollup merge of #72804 - estebank:opaque-missing-lts-in-fn-2, r=nikom…
Manishearth Jun 16, 2020
00816ca
Rollup merge of #73065 - Amanieu:tls-fix, r=oli-obk
Manishearth Jun 16, 2020
289dabd
Rollup merge of #73103 - ecstatic-morse:replace-body-with-loop, r=pnk…
Manishearth Jun 16, 2020
16b1a49
Rollup merge of #73136 - alexcrichton:thinlto-compiler-builtins, r=Ma…
Manishearth Jun 16, 2020
c824b3b
Rollup merge of #73352 - ehuss:bootstrap-metadata, r=Mark-Simulacrum
Manishearth Jun 16, 2020
b2b67e4
Rollup merge of #73361 - estebank:non-primitive-cast, r=davidtwco
Manishearth Jun 16, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Consider fewer predicates for projection candidates
We now require that projection candidates are applicable with the
idenitity substs of the trait, rather than allowing predicates that are
only applicable for certain substs.
  • Loading branch information
matthewjasper committed Jun 10, 2020
commit d14ee0b5b921013b4516a55323d9b9ce655bf391
7 changes: 7 additions & 0 deletions src/librustc_middle/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,13 @@ rustc_queries! {
cache_on_disk_if { key.is_local() }
}

/// Returns the list of predicates that can be used for
/// `SelectionCandidate::ProjectionCandidate` and
/// `ProjectionTyCandidate::TraitDef`.
query projection_predicates(key: DefId) -> &'tcx ty::List<ty::Predicate<'tcx>> {
desc { |tcx| "finding projection predicates for `{}`", tcx.def_path_str(key) }
}

query native_libraries(_: CrateNum) -> Lrc<Vec<NativeLib>> {
desc { "looking up the native libraries of a linked crate" }
}
Expand Down
11 changes: 11 additions & 0 deletions src/librustc_middle/ty/subst.rs
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,17 @@ impl<'a, 'tcx> InternalSubsts<'tcx> {
/// in a different item, with `target_substs` as the base for
/// the target impl/trait, with the source child-specific
/// parameters (e.g., method parameters) on top of that base.
///
/// For example given:
///
/// trait X<S> { fn f<T>(); }
/// impl<U> X<U> for U { fn f<V>() {} }
///
/// * If `self` is `[Self, S, T]`: the identity substs of `f` in the trait.
/// * If `source_ancestor` is the def_id of the trait.
/// * If `target_substs` is `[U]`, the substs for the impl.
/// * Then we will return `[U, T]`, the subst for `f` in the impl that
/// are needed for it to match the trait.
pub fn rebase_onto(
&self,
tcx: TyCtxt<'tcx>,
Expand Down
21 changes: 13 additions & 8 deletions src/librustc_trait_selection/traits/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -895,9 +895,12 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>(

let tcx = selcx.tcx();
// Check whether the self-type is itself a projection.
let (def_id, substs) = match obligation_trait_ref.self_ty().kind {
ty::Projection(ref data) => (data.trait_ref(tcx).def_id, data.substs),
ty::Opaque(def_id, substs) => (def_id, substs),
// If so, extract what we know from the trait and try to come up with a good answer.
let bounds = match obligation_trait_ref.self_ty().kind {
ty::Projection(ref data) => {
tcx.projection_predicates(data.item_def_id).subst(tcx, data.substs)
}
ty::Opaque(def_id, substs) => tcx.projection_predicates(def_id).subst(tcx, substs),
ty::Infer(ty::TyVar(_)) => {
// If the self-type is an inference variable, then it MAY wind up
// being a projected type, so induce an ambiguity.
Expand All @@ -907,17 +910,13 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>(
_ => return,
};

// If so, extract what we know from the trait and try to come up with a good answer.
let trait_predicates = tcx.predicates_of(def_id);
let bounds = trait_predicates.instantiate(tcx, substs);
let bounds = elaborate_predicates(tcx, bounds.predicates.into_iter()).map(|o| o.predicate);
assemble_candidates_from_predicates(
selcx,
obligation,
obligation_trait_ref,
candidate_set,
ProjectionTyCandidate::TraitDef,
bounds,
bounds.iter(),
)
}

Expand Down Expand Up @@ -1474,6 +1473,12 @@ fn confirm_impl_candidate<'cx, 'tcx>(
);
return Progress { ty: tcx.types.err, obligations: nested };
}
// If we're trying to normalize `<Vec<u32> as X>::A<S>` using
//`impl<T> X for Vec<T> { type A<Y> = Box<Y>; }`, then:
//
// * `obligation.predicate.substs` is `[Vec<u32>, S]`
// * `substs` is `[u32]`
// * `substs` ends up as `[u32, S]`
let substs = obligation.predicate.substs.rebase_onto(tcx, trait_def_id, substs);
let substs =
translate_substs(selcx.infcx(), param_env, impl_def_id, substs, assoc_ty.defining_node);
Expand Down
50 changes: 22 additions & 28 deletions src/librustc_trait_selection/traits/select/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1265,9 +1265,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
placeholder_trait_predicate,
);

let (def_id, substs) = match placeholder_trait_predicate.trait_ref.self_ty().kind {
ty::Projection(ref data) => (data.trait_ref(self.tcx()).def_id, data.substs),
ty::Opaque(def_id, substs) => (def_id, substs),
let tcx = self.infcx.tcx;
let predicates = match placeholder_trait_predicate.trait_ref.self_ty().kind {
ty::Projection(ref data) => {
tcx.projection_predicates(data.item_def_id).subst(tcx, data.substs)
}
ty::Opaque(def_id, substs) => tcx.projection_predicates(def_id).subst(tcx, substs),
_ => {
span_bug!(
obligation.cause.span,
Expand All @@ -1277,32 +1280,23 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
);
}
};
debug!(
"match_projection_obligation_against_definition_bounds: \
def_id={:?}, substs={:?}",
def_id, substs
);

let predicates_of = self.tcx().predicates_of(def_id);
let bounds = predicates_of.instantiate(self.tcx(), substs);
debug!(
"match_projection_obligation_against_definition_bounds: \
bounds={:?}",
bounds
);

let elaborated_predicates =
util::elaborate_predicates(self.tcx(), bounds.predicates.into_iter());
let matching_bound = elaborated_predicates.filter_to_traits().find(|bound| {
self.infcx.probe(|_| {
self.match_projection(
obligation,
*bound,
placeholder_trait_predicate.trait_ref,
&placeholder_map,
snapshot,
)
})
let matching_bound = predicates.iter().find_map(|bound| {
if let ty::PredicateKind::Trait(bound, _) = bound.kind() {
let bound = bound.to_poly_trait_ref();
if self.infcx.probe(|_| {
self.match_projection(
obligation,
bound,
placeholder_trait_predicate.trait_ref,
&placeholder_map,
snapshot,
)
}) {
return Some(bound);
}
}
None
});

debug!(
Expand Down
102 changes: 101 additions & 1 deletion src/librustc_ty/ty.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
use rustc_data_structures::svh::Svh;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
use rustc_infer::traits::util;
use rustc_middle::hir::map as hir_map;
use rustc_middle::ty::subst::Subst;
use rustc_middle::ty::subst::{InternalSubsts, Subst};
use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness};
use rustc_session::CrateDisambiguator;
use rustc_span::symbol::Symbol;
Expand Down Expand Up @@ -367,6 +369,103 @@ fn asyncness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::IsAsync {
fn_like.asyncness()
}

/// For associated types we allow bounds written on the associated type
/// (`type X: Trait`) to be used as candidates. We also allow the same bounds
/// when desugared as bounds on the trait `where Self::X: Trait`.
///
/// Note that this filtering is done with the trait's identity substs to
/// simplify checking that these bounds are met in impls. This means that
/// a bound such as `for<'b> <Self as X<'b>>::U: Clone` can't be used, as in
/// `hr-associated-type-bound-1.rs`.
fn associated_type_projection_predicates(
tcx: TyCtxt<'_>,
def_id: DefId,
) -> &'_ ty::List<ty::Predicate<'_>> {
let trait_id = tcx.associated_item(def_id).container.id();
let trait_substs = InternalSubsts::identity_for_item(tcx, trait_id);

let generic_trait_bounds = tcx.predicates_of(trait_id);
let trait_bounds = generic_trait_bounds.instantiate_identity(tcx);
let trait_predicates = util::elaborate_predicates(tcx, trait_bounds.predicates.into_iter());

let predicates = trait_predicates.filter_map(|obligation| {
let pred = obligation.predicate;
match pred.kind() {
ty::PredicateKind::Trait(tr, _) => {
if let ty::Projection(p) = tr.skip_binder().self_ty().kind {
if p.item_def_id == def_id && p.substs.starts_with(trait_substs) {
return Some(pred);
}
}
}
ty::PredicateKind::Projection(proj) => {
if let ty::Projection(p) = proj.skip_binder().projection_ty.self_ty().kind {
if p.item_def_id == def_id && p.substs.starts_with(trait_substs) {
return Some(pred);
}
}
}
_ => {}
}
None
});

let result = tcx.mk_predicates(predicates);
debug!("associated_type_projection_predicates({}) = {:?}", tcx.def_path_str(def_id), result);
result
}

/// Opaque types might not have the same issues as associated types, but we use a
/// similar filtering for consistency.
fn opaque_type_projection_predicates(
tcx: TyCtxt<'_>,
def_id: DefId,
) -> &'_ ty::List<ty::Predicate<'_>> {
let substs = InternalSubsts::identity_for_item(tcx, def_id);

let generics_bounds = tcx.predicates_of(def_id);
let bounds = generics_bounds.instantiate_identity(tcx);
let predicates = util::elaborate_predicates(tcx, bounds.predicates.into_iter());

let filtered_predicates = predicates.filter_map(|obligation| {
let pred = obligation.predicate;
match pred.kind() {
ty::PredicateKind::Trait(tr, _) => {
if let ty::Opaque(opaque_def_id, opaque_substs) = tr.skip_binder().self_ty().kind {
if opaque_def_id == def_id && opaque_substs == substs {
return Some(pred);
}
}
}
ty::PredicateKind::Projection(proj) => {
if let ty::Opaque(opaque_def_id, opaque_substs) =
proj.skip_binder().projection_ty.self_ty().kind
{
if opaque_def_id == def_id && opaque_substs == substs {
return Some(pred);
}
}
}
_ => {}
}
None
});

let result = tcx.mk_predicates(filtered_predicates);
debug!("opaque_type_projection_predicates({}) = {:?}", tcx.def_path_str(def_id), result);
result
}

fn projection_predicates(tcx: TyCtxt<'_>, def_id: DefId) -> &'_ ty::List<ty::Predicate<'_>> {
match tcx.def_kind(def_id) {
DefKind::AssocTy => associated_type_projection_predicates(tcx, def_id),
DefKind::OpaqueTy | DefKind::AssocOpaqueTy => {
opaque_type_projection_predicates(tcx, def_id)
}
k => bug!("projection_predicates called on {}", k.descr(def_id)),
}
}

pub fn provide(providers: &mut ty::query::Providers<'_>) {
*providers = ty::query::Providers {
asyncness,
Expand All @@ -383,6 +482,7 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) {
instance_def_size_estimate,
issue33140_self_ty,
impl_defaultness,
projection_predicates,
..*providers
};
}
2 changes: 1 addition & 1 deletion src/librustc_typeck/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2124,7 +2124,7 @@ fn check_impl_items_against_trait<'tcx>(
&ty_trait_item,
impl_trait_ref,
opt_trait_span,
)
);
} else {
let mut err = struct_span_err!(
tcx.sess,
Expand Down
18 changes: 18 additions & 0 deletions src/test/ui/associated-types/hr-associated-type-bound-1.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
trait X<'a>
where
for<'b> <Self as X<'b>>::U: Clone,
{
type U: ?Sized;
fn f(&self, x: &Self::U) {
<Self::U>::clone(x);
}
}

impl X<'_> for i32 {
type U = str;
//~^ ERROR the trait bound `for<'b> <i32 as X<'b>>::U: std::clone::Clone`
}

fn main() {
1i32.f("abc");
}
19 changes: 19 additions & 0 deletions src/test/ui/associated-types/hr-associated-type-bound-1.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
error[E0277]: the trait bound `for<'b> <i32 as X<'b>>::U: std::clone::Clone` is not satisfied
--> $DIR/hr-associated-type-bound-1.rs:12:14
|
LL | trait X<'a>
| - required by a bound in this
LL | where
LL | for<'b> <Self as X<'b>>::U: Clone,
| ----- required by this bound in `X`
...
LL | type U = str;
| ^^^ the trait `for<'b> std::clone::Clone` is not implemented for `<i32 as X<'b>>::U`
|
= help: the following implementations were found:
<&T as std::clone::Clone>
<&mut T as std::clone::Clone>

error: aborting due to previous error

For more information about this error, try `rustc --explain E0277`.
21 changes: 21 additions & 0 deletions src/test/ui/associated-types/hr-associated-type-bound-2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
trait X<'a>
where
for<'b> <Self as X<'b>>::U: Clone,
{
type U: ?Sized;
fn f(&self, x: &Self::U) {
<Self::U>::clone(x);
}
}

impl X<'_> for u32
where
for<'b> <Self as X<'b>>::U: Clone,
{
type U = str;
}

fn main() {
1u32.f("abc");
//~^ ERROR no method named `f` found for type `u32` in the current scope
}
13 changes: 13 additions & 0 deletions src/test/ui/associated-types/hr-associated-type-bound-2.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
error[E0599]: no method named `f` found for type `u32` in the current scope
--> $DIR/hr-associated-type-bound-2.rs:19:10
|
LL | 1u32.f("abc");
| ^ method not found in `u32`
|
= note: the method `f` exists but the following trait bounds were not satisfied:
`<u32 as X<'b>>::U: std::clone::Clone`
which is required by `u32: X`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0599`.
14 changes: 14 additions & 0 deletions src/test/ui/associated-types/hr-associated-type-bound-object.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
trait X<'a>
where
for<'b> <Self as X<'b>>::U: Clone,
{
type U: ?Sized;
}
fn f<'a, T: X<'a> + ?Sized>(x: &<T as X<'a>>::U) {
//~^ ERROR the trait bound `for<'b> <T as X<'b>>::U: std::clone::Clone` is not satisfied
<<T as X<'_>>::U>::clone(x);
}

pub fn main() {
f::<dyn X<'_, U = str>>("abc");
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
error[E0277]: the trait bound `for<'b> <T as X<'b>>::U: std::clone::Clone` is not satisfied
--> $DIR/hr-associated-type-bound-object.rs:7:13
|
LL | trait X<'a>
| - required by a bound in this
LL | where
LL | for<'b> <Self as X<'b>>::U: Clone,
| ----- required by this bound in `X`
...
LL | fn f<'a, T: X<'a> + ?Sized>(x: &<T as X<'a>>::U) {
| ^^^^^ the trait `for<'b> std::clone::Clone` is not implemented for `<T as X<'b>>::U`
|
= help: the following implementations were found:
<&T as std::clone::Clone>
<&mut T as std::clone::Clone>

error: aborting due to previous error

For more information about this error, try `rustc --explain E0277`.
Loading