Skip to content

Commit d4abb08

Browse files
committed
Auto merge of rust-lang#61919 - alexreg:fix-atb-1, r=nikomatsakis
Fix for "ambiguous associated type" issue with ATBs Fixes rust-lang#61752. r? @nikomatsakis CC @Centril
2 parents 5421d94 + 0410e32 commit d4abb08

File tree

11 files changed

+157
-91
lines changed

11 files changed

+157
-91
lines changed

src/librustc/hir/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2234,7 +2234,7 @@ pub enum UseKind {
22342234
#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
22352235
pub struct TraitRef {
22362236
pub path: P<Path>,
2237-
// Don't hash the ref_id. It is tracked via the thing it is used to access
2237+
// Don't hash the `ref_id`. It is tracked via the thing it is used to access.
22382238
#[stable_hasher(ignore)]
22392239
pub hir_ref_id: HirId,
22402240
}

src/librustc/ty/mod.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -904,7 +904,7 @@ pub struct Generics {
904904
pub parent_count: usize,
905905
pub params: Vec<GenericParamDef>,
906906

907-
/// Reverse map to the `index` field of each `GenericParamDef`
907+
/// Reverse map to the `index` field of each `GenericParamDef`.
908908
#[stable_hasher(ignore)]
909909
pub param_def_id_to_index: FxHashMap<DefId, u32>,
910910

@@ -1252,7 +1252,7 @@ impl<'tcx> TraitPredicate<'tcx> {
12521252

12531253
impl<'tcx> PolyTraitPredicate<'tcx> {
12541254
pub fn def_id(&self) -> DefId {
1255-
// Ok to skip binder since trait def-ID does not care about regions.
1255+
// Ok to skip binder since trait `DefId` does not care about regions.
12561256
self.skip_binder().def_id()
12571257
}
12581258
}
@@ -1319,7 +1319,7 @@ impl<'tcx> PolyProjectionPredicate<'tcx> {
13191319
/// Note that this is not the `DefId` of the `TraitRef` containing this
13201320
/// associated type, which is in `tcx.associated_item(projection_def_id()).container`.
13211321
pub fn projection_def_id(&self) -> DefId {
1322-
// Ok to skip binder since trait def-ID does not care about regions.
1322+
// Ok to skip binder since trait `DefId` does not care about regions.
13231323
self.skip_binder().projection_ty.item_def_id
13241324
}
13251325
}
@@ -1646,9 +1646,9 @@ pub type PlaceholderConst = Placeholder<BoundVar>;
16461646
/// particular point.
16471647
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)]
16481648
pub struct ParamEnv<'tcx> {
1649-
/// Obligations that the caller must satisfy. This is basically
1649+
/// `Obligation`s that the caller must satisfy. This is basically
16501650
/// the set of bounds on the in-scope type parameters, translated
1651-
/// into Obligations, and elaborated and normalized.
1651+
/// into `Obligation`s, and elaborated and normalized.
16521652
pub caller_bounds: &'tcx List<ty::Predicate<'tcx>>,
16531653

16541654
/// Typically, this is `Reveal::UserFacing`, but during codegen we
@@ -2796,7 +2796,7 @@ impl<'tcx> TyCtxt<'tcx> {
27962796
_ => false,
27972797
}
27982798
} else {
2799-
match self.def_kind(def_id).expect("no def for def-id") {
2799+
match self.def_kind(def_id).expect("no def for `DefId`") {
28002800
DefKind::AssocConst
28012801
| DefKind::Method
28022802
| DefKind::AssocTy => true,

src/librustc/ty/sty.rs

+7-6
Original file line numberDiff line numberDiff line change
@@ -646,7 +646,7 @@ impl<'tcx> List<ExistentialPredicate<'tcx>> {
646646
///
647647
/// A Rust trait object type consists (in addition to a lifetime bound)
648648
/// of a set of trait bounds, which are separated into any number
649-
/// of auto-trait bounds, and at most 1 non-auto-trait bound. The
649+
/// of auto-trait bounds, and at most one non-auto-trait bound. The
650650
/// non-auto-trait bound is called the "principal" of the trait
651651
/// object.
652652
///
@@ -680,7 +680,8 @@ impl<'tcx> List<ExistentialPredicate<'tcx>> {
680680

681681
#[inline]
682682
pub fn projection_bounds<'a>(&'a self) ->
683-
impl Iterator<Item=ExistentialProjection<'tcx>> + 'a {
683+
impl Iterator<Item = ExistentialProjection<'tcx>> + 'a
684+
{
684685
self.iter().filter_map(|predicate| {
685686
match *predicate {
686687
ExistentialPredicate::Projection(p) => Some(p),
@@ -690,7 +691,7 @@ impl<'tcx> List<ExistentialPredicate<'tcx>> {
690691
}
691692

692693
#[inline]
693-
pub fn auto_traits<'a>(&'a self) -> impl Iterator<Item=DefId> + 'a {
694+
pub fn auto_traits<'a>(&'a self) -> impl Iterator<Item = DefId> + 'a {
694695
self.iter().filter_map(|predicate| {
695696
match *predicate {
696697
ExistentialPredicate::AutoTrait(d) => Some(d),
@@ -711,17 +712,17 @@ impl<'tcx> Binder<&'tcx List<ExistentialPredicate<'tcx>>> {
711712

712713
#[inline]
713714
pub fn projection_bounds<'a>(&'a self) ->
714-
impl Iterator<Item=PolyExistentialProjection<'tcx>> + 'a {
715+
impl Iterator<Item = PolyExistentialProjection<'tcx>> + 'a {
715716
self.skip_binder().projection_bounds().map(Binder::bind)
716717
}
717718

718719
#[inline]
719-
pub fn auto_traits<'a>(&'a self) -> impl Iterator<Item=DefId> + 'a {
720+
pub fn auto_traits<'a>(&'a self) -> impl Iterator<Item = DefId> + 'a {
720721
self.skip_binder().auto_traits()
721722
}
722723

723724
pub fn iter<'a>(&'a self)
724-
-> impl DoubleEndedIterator<Item=Binder<ExistentialPredicate<'tcx>>> + 'tcx {
725+
-> impl DoubleEndedIterator<Item = Binder<ExistentialPredicate<'tcx>>> + 'tcx {
725726
self.skip_binder().iter().cloned().map(Binder::bind)
726727
}
727728
}

src/librustc_codegen_llvm/debuginfo/metadata.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -450,11 +450,11 @@ fn subroutine_type_metadata(
450450
false);
451451
}
452452

453-
// FIXME(1563) This is all a bit of a hack because 'trait pointer' is an ill-
454-
// defined concept. For the case of an actual trait pointer (i.e., Box<Trait>,
455-
// &Trait), trait_object_type should be the whole thing (e.g, Box<Trait>) and
456-
// trait_type should be the actual trait (e.g., Trait). Where the trait is part
457-
// of a DST struct, there is no trait_object_type and the results of this
453+
// FIXME(1563): This is all a bit of a hack because 'trait pointer' is an ill-
454+
// defined concept. For the case of an actual trait pointer (i.e., `Box<Trait>`,
455+
// `&Trait`), `trait_object_type` should be the whole thing (e.g, `Box<Trait>`) and
456+
// `trait_type` should be the actual trait (e.g., `Trait`). Where the trait is part
457+
// of a DST struct, there is no `trait_object_type` and the results of this
458458
// function will be a little bit weird.
459459
fn trait_pointer_metadata(
460460
cx: &CodegenCx<'ll, 'tcx>,
@@ -464,13 +464,13 @@ fn trait_pointer_metadata(
464464
) -> &'ll DIType {
465465
// The implementation provided here is a stub. It makes sure that the trait
466466
// type is assigned the correct name, size, namespace, and source location.
467-
// But it does not describe the trait's methods.
467+
// However, it does not describe the trait's methods.
468468

469469
let containing_scope = match trait_type.sty {
470470
ty::Dynamic(ref data, ..) =>
471471
data.principal_def_id().map(|did| get_namespace_for_item(cx, did)),
472472
_ => {
473-
bug!("debuginfo: Unexpected trait-object type in \
473+
bug!("debuginfo: unexpected trait-object type in \
474474
trait_pointer_metadata(): {:?}",
475475
trait_type);
476476
}

src/librustc_privacy/lib.rs

+10-5
Original file line numberDiff line numberDiff line change
@@ -1050,14 +1050,19 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
10501050
if !self.in_body {
10511051
// Avoid calling `hir_trait_to_predicates` in bodies, it will ICE.
10521052
// The traits' privacy in bodies is already checked as a part of trait object types.
1053-
let (principal, bounds) = rustc_typeck::hir_trait_to_predicates(self.tcx, trait_ref);
1054-
if self.visit_trait(*principal.skip_binder()) {
1055-
return;
1053+
let bounds = rustc_typeck::hir_trait_to_predicates(self.tcx, trait_ref);
1054+
1055+
for (trait_predicate, _) in bounds.trait_bounds {
1056+
if self.visit_trait(*trait_predicate.skip_binder()) {
1057+
return;
1058+
}
10561059
}
1060+
10571061
for (poly_predicate, _) in bounds.projection_bounds {
10581062
let tcx = self.tcx;
1059-
if self.visit(poly_predicate.skip_binder().ty) ||
1060-
self.visit_trait(poly_predicate.skip_binder().projection_ty.trait_ref(tcx)) {
1063+
if self.visit(poly_predicate.skip_binder().ty)
1064+
|| self.visit_trait(poly_predicate.skip_binder().projection_ty.trait_ref(tcx))
1065+
{
10611066
return;
10621067
}
10631068
}

src/librustc_typeck/astconv.rs

+57-38
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,17 @@ pub struct PathSeg(pub DefId, pub usize);
4242
pub trait AstConv<'tcx> {
4343
fn tcx<'a>(&'a self) -> TyCtxt<'tcx>;
4444

45-
/// Returns the set of bounds in scope for the type parameter with
46-
/// the given id.
45+
/// Returns predicates in scope of the form `X: Foo`, where `X` is
46+
/// a type parameter `X` with the given id `def_id`. This is a
47+
/// subset of the full set of predicates.
48+
///
49+
/// This is used for one specific purpose: resolving "short-hand"
50+
/// associated type references like `T::Item`. In principle, we
51+
/// would do that by first getting the full set of predicates in
52+
/// scope and then filtering down to find those that apply to `T`,
53+
/// but this can lead to cycle errors. The problem is that we have
54+
/// to do this resolution *in order to create the predicates in
55+
/// the first place*. Hence, we have this "special pass".
4756
fn get_type_parameter_bounds(&self, span: Span, def_id: DefId)
4857
-> &'tcx ty::GenericPredicates<'tcx>;
4958

@@ -775,11 +784,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
775784
/// The given trait-ref must actually be a trait.
776785
pub(super) fn instantiate_poly_trait_ref_inner(&self,
777786
trait_ref: &hir::TraitRef,
787+
span: Span,
778788
self_ty: Ty<'tcx>,
779789
bounds: &mut Bounds<'tcx>,
780790
speculative: bool,
781-
) -> (ty::PolyTraitRef<'tcx>, Option<Vec<Span>>)
782-
{
791+
) -> Option<Vec<Span>> {
783792
let trait_def_id = trait_ref.trait_def_id();
784793

785794
debug!("instantiate_poly_trait_ref({:?}, def_id={:?})", trait_ref, trait_def_id);
@@ -794,6 +803,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
794803
);
795804
let poly_trait_ref = ty::Binder::bind(ty::TraitRef::new(trait_def_id, substs));
796805

806+
bounds.trait_bounds.push((poly_trait_ref, span));
807+
797808
let mut dup_bindings = FxHashMap::default();
798809
for binding in &assoc_bindings {
799810
// Specify type to assert that error was already reported in `Err` case.
@@ -804,14 +815,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
804815
binding,
805816
bounds,
806817
speculative,
807-
&mut dup_bindings
818+
&mut dup_bindings,
808819
);
809820
// Okay to ignore `Err` because of `ErrorReported` (see above).
810821
}
811822

812823
debug!("instantiate_poly_trait_ref({:?}, bounds={:?}) -> {:?}",
813824
trait_ref, bounds, poly_trait_ref);
814-
(poly_trait_ref, potential_assoc_types)
825+
potential_assoc_types
815826
}
816827

817828
/// Given a trait bound like `Debug`, applies that trait bound the given self-type to construct
@@ -836,10 +847,15 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
836847
pub fn instantiate_poly_trait_ref(&self,
837848
poly_trait_ref: &hir::PolyTraitRef,
838849
self_ty: Ty<'tcx>,
839-
bounds: &mut Bounds<'tcx>
840-
) -> (ty::PolyTraitRef<'tcx>, Option<Vec<Span>>)
841-
{
842-
self.instantiate_poly_trait_ref_inner(&poly_trait_ref.trait_ref, self_ty, bounds, false)
850+
bounds: &mut Bounds<'tcx>,
851+
) -> Option<Vec<Span>> {
852+
self.instantiate_poly_trait_ref_inner(
853+
&poly_trait_ref.trait_ref,
854+
poly_trait_ref.span,
855+
self_ty,
856+
bounds,
857+
false,
858+
)
843859
}
844860

845861
fn ast_path_to_mono_trait_ref(&self,
@@ -983,12 +999,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
983999
}
9841000

9851001
for bound in trait_bounds {
986-
let (poly_trait_ref, _) = self.instantiate_poly_trait_ref(
1002+
let _ = self.instantiate_poly_trait_ref(
9871003
bound,
9881004
param_ty,
9891005
bounds,
9901006
);
991-
bounds.trait_bounds.push((poly_trait_ref, bound.span))
9921007
}
9931008

9941009
bounds.region_bounds.extend(region_bounds
@@ -1172,11 +1187,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
11721187
// Calling `skip_binder` is okay, because `add_bounds` expects the `param_ty`
11731188
// parameter to have a skipped binder.
11741189
let param_ty = tcx.mk_projection(assoc_ty.def_id, candidate.skip_binder().substs);
1175-
self.add_bounds(
1176-
param_ty,
1177-
ast_bounds,
1178-
bounds,
1179-
);
1190+
self.add_bounds(param_ty, ast_bounds, bounds);
11801191
}
11811192
}
11821193
Ok(())
@@ -1216,25 +1227,19 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
12161227
let mut bounds = Bounds::default();
12171228
let mut potential_assoc_types = Vec::new();
12181229
let dummy_self = self.tcx().types.trait_object_dummy_self;
1219-
// FIXME: we want to avoid collecting into a `Vec` here, but simply cloning the iterator is
1220-
// not straightforward due to the borrow checker.
1221-
let bound_trait_refs: Vec<_> = trait_bounds
1222-
.iter()
1223-
.rev()
1224-
.map(|trait_bound| {
1225-
let (trait_ref, cur_potential_assoc_types) = self.instantiate_poly_trait_ref(
1226-
trait_bound,
1227-
dummy_self,
1228-
&mut bounds,
1229-
);
1230-
potential_assoc_types.extend(cur_potential_assoc_types.into_iter().flatten());
1231-
(trait_ref, trait_bound.span)
1232-
})
1233-
.collect();
1230+
for trait_bound in trait_bounds.iter().rev() {
1231+
let cur_potential_assoc_types = self.instantiate_poly_trait_ref(
1232+
trait_bound,
1233+
dummy_self,
1234+
&mut bounds,
1235+
);
1236+
potential_assoc_types.extend(cur_potential_assoc_types.into_iter().flatten());
1237+
}
12341238

12351239
// Expand trait aliases recursively and check that only one regular (non-auto) trait
12361240
// is used and no 'maybe' bounds are used.
1237-
let expanded_traits = traits::expand_trait_aliases(tcx, bound_trait_refs.iter().cloned());
1241+
let expanded_traits =
1242+
traits::expand_trait_aliases(tcx, bounds.trait_bounds.iter().cloned());
12381243
let (mut auto_traits, regular_traits): (Vec<_>, Vec<_>) =
12391244
expanded_traits.partition(|i| tcx.trait_is_auto(i.trait_ref().def_id()));
12401245
if regular_traits.len() > 1 {
@@ -1276,7 +1281,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
12761281
// Use a `BTreeSet` to keep output in a more consistent order.
12771282
let mut associated_types = BTreeSet::default();
12781283

1279-
let regular_traits_refs = bound_trait_refs
1284+
let regular_traits_refs = bounds.trait_bounds
12801285
.into_iter()
12811286
.filter(|(trait_ref, _)| !tcx.trait_is_auto(trait_ref.def_id()))
12821287
.map(|(trait_ref, _)| trait_ref);
@@ -1491,7 +1496,17 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
14911496
{
14921497
let tcx = self.tcx();
14931498

1499+
debug!(
1500+
"find_bound_for_assoc_item(ty_param_def_id={:?}, assoc_name={:?}, span={:?})",
1501+
ty_param_def_id,
1502+
assoc_name,
1503+
span,
1504+
);
1505+
14941506
let predicates = &self.get_type_parameter_bounds(span, ty_param_def_id).predicates;
1507+
1508+
debug!("find_bound_for_assoc_item: predicates={:#?}", predicates);
1509+
14951510
let bounds = predicates.iter().filter_map(|(p, _)| p.to_opt_poly_trait_ref());
14961511

14971512
// Check that there is exactly one way to find an associated type with the
@@ -1515,7 +1530,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
15151530
assoc_name: ast::Ident,
15161531
span: Span)
15171532
-> Result<ty::PolyTraitRef<'tcx>, ErrorReported>
1518-
where I: Iterator<Item=ty::PolyTraitRef<'tcx>>
1533+
where I: Iterator<Item = ty::PolyTraitRef<'tcx>>
15191534
{
15201535
let bound = match bounds.next() {
15211536
Some(bound) => bound,
@@ -1524,13 +1539,17 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
15241539
"associated type `{}` not found for `{}`",
15251540
assoc_name,
15261541
ty_param_name)
1527-
.span_label(span, format!("associated type `{}` not found", assoc_name))
1528-
.emit();
1542+
.span_label(span, format!("associated type `{}` not found", assoc_name))
1543+
.emit();
15291544
return Err(ErrorReported);
15301545
}
15311546
};
15321547

1548+
debug!("one_bound_for_assoc_type: bound = {:?}", bound);
1549+
15331550
if let Some(bound2) = bounds.next() {
1551+
debug!("one_bound_for_assoc_type: bound2 = {:?}", bound2);
1552+
15341553
let bounds = iter::once(bound).chain(iter::once(bound2)).chain(bounds);
15351554
let mut err = struct_span_err!(
15361555
self.tcx().sess, span, E0221,
@@ -1544,7 +1563,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
15441563
item.kind == ty::AssocKind::Type &&
15451564
self.tcx().hygienic_eq(assoc_name, item.ident, bound.def_id())
15461565
})
1547-
.and_then(|item| self.tcx().hir().span_if_local(item.def_id));
1566+
.and_then(|item| self.tcx().hir().span_if_local(item.def_id));
15481567

15491568
if let Some(span) = bound_span {
15501569
err.span_label(span, format!("ambiguous `{}` from `{}`",

src/librustc_typeck/check/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2030,7 +2030,7 @@ fn report_unexpected_variant_res(tcx: TyCtxt<'_>, res: Res, span: Span, qpath: &
20302030
impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
20312031
fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
20322032
self.tcx
2033-
}
2033+
}
20342034

20352035
fn get_type_parameter_bounds(&self, _: Span, def_id: DefId)
20362036
-> &'tcx ty::GenericPredicates<'tcx>

0 commit comments

Comments
 (0)