Skip to content

Skip implicit Sized bound for GATs' generics #87275

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 1 addition & 2 deletions compiler/rustc_trait_selection/src/traits/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -327,8 +327,7 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> {

fn fold<T: TypeFoldable<'tcx>>(&mut self, value: T) -> T {
let value = self.selcx.infcx().resolve_vars_if_possible(value);
debug!(?value);

debug!(?value, "fold");
assert!(
!value.has_escaping_bound_vars(),
"Normalizing {:?} without wrapping in a `Binder`",
Expand Down
15 changes: 14 additions & 1 deletion compiler/rustc_trait_selection/src/traits/select/confirmation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let tcx = self.tcx();

let trait_predicate = self.infcx.shallow_resolve(obligation.predicate);
debug!(?trait_predicate);

let placeholder_trait_predicate =
self.infcx().replace_bound_vars_with_placeholders(trait_predicate);
debug!(?placeholder_trait_predicate);

let placeholder_self_ty = placeholder_trait_predicate.self_ty();
let (def_id, substs) = match *placeholder_self_ty.kind() {
ty::Projection(proj) => (proj.item_def_id, proj.substs),
Expand All @@ -140,9 +144,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
};

let candidate_predicate = tcx.item_bounds(def_id)[idx].subst(tcx, substs);
debug!("candidate predicate before poly trait = {:?}", candidate_predicate);

let candidate = candidate_predicate
.to_opt_poly_trait_ref()
.expect("projection candidate is not a trait predicate");
debug!("candidate predicate after poly trait = {:?}", candidate_predicate);

let mut obligations = Vec::new();
let candidate = normalize_with_depth_to(
self,
Expand All @@ -162,7 +170,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
})?);

if let ty::Projection(..) = placeholder_self_ty.kind() {
for predicate in tcx.predicates_of(def_id).instantiate_own(tcx, substs).predicates {
let predicates = tcx.predicates_of(def_id);
debug!(?predicates);
let instantiated_predicates = predicates.instantiate_own(tcx, substs);
debug!(?instantiated_predicates);
for predicate in instantiated_predicates.predicates {
let normalized = normalize_with_depth_to(
self,
obligation.param_env,
Expand All @@ -179,6 +191,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
));
}
}
debug!(?obligations);

Ok(obligations)
})
Expand Down
8 changes: 6 additions & 2 deletions compiler/rustc_trait_selection/src/traits/select/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -868,7 +868,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
where
I: Iterator<Item = ty::Predicate<'tcx>>,
{
cycle.all(|predicate| self.coinductive_predicate(predicate))
cycle.all(|predicate| {
debug!(?predicate, "coinductive_match");
self.coinductive_predicate(predicate)
})
}

fn coinductive_predicate(&self, predicate: ty::Predicate<'tcx>) -> bool {
Expand Down Expand Up @@ -1572,8 +1575,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {

// NOTE: binder moved to (*)
let self_ty = self.infcx.shallow_resolve(obligation.predicate.skip_binder().self_ty());
debug!(?self_ty, "sized_conditions");

match self_ty.kind() {
match *self_ty.kind() {
ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
| ty::Uint(_)
| ty::Int(_)
Expand Down
21 changes: 13 additions & 8 deletions compiler/rustc_typeck/src/bounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,17 +53,22 @@ impl<'tcx> Bounds<'tcx> {
&self,
tcx: TyCtxt<'tcx>,
param_ty: Ty<'tcx>,
skip_implicit_sized: bool,
) -> Vec<(ty::Predicate<'tcx>, Span)> {
// If it could be sized, and is, add the `Sized` predicate.
let sized_predicate = self.implicitly_sized.and_then(|span| {
tcx.lang_items().sized_trait().map(|sized| {
let trait_ref = ty::Binder::dummy(ty::TraitRef {
def_id: sized,
substs: tcx.mk_substs_trait(param_ty, &[]),
});
(trait_ref.without_const().to_predicate(tcx), span)
let sized_predicate = if skip_implicit_sized {
None
} else {
self.implicitly_sized.and_then(|span| {
tcx.lang_items().sized_trait().map(|sized| {
let trait_ref = ty::Binder::dummy(ty::TraitRef {
def_id: sized,
substs: tcx.mk_substs_trait(param_ty, &[]),
});
(trait_ref.without_const().to_predicate(tcx), span)
})
})
});
};

sized_predicate
.into_iter()
Expand Down
65 changes: 57 additions & 8 deletions compiler/rustc_typeck/src/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1170,7 +1170,7 @@ fn super_predicates_that_define_assoc_type(
)
};

let superbounds1 = superbounds1.predicates(tcx, self_param_ty);
let superbounds1 = superbounds1.predicates(tcx, self_param_ty, false);

// Convert any explicit superbounds in the where-clause,
// e.g., `trait Foo where Self: Bar`.
Expand Down Expand Up @@ -1978,6 +1978,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP

let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
let node = tcx.hir().get(hir_id);
debug!("explicit_predicates_of: node = {:?}", node);

let mut is_trait = None;
let mut is_default_impl_trait = None;
Expand All @@ -1991,10 +1992,22 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
// Preserving the order of insertion is important here so as not to break UI tests.
let mut predicates: FxIndexSet<(ty::Predicate<'_>, Span)> = FxIndexSet::default();

let mut is_associated_type = false;

let ast_generics = match node {
Node::TraitItem(item) => &item.generics,
Node::TraitItem(item) => {
if matches!(item.kind, TraitItemKind::Type(..)) {
is_associated_type = true;
}
&item.generics
}

Node::ImplItem(item) => &item.generics,
Node::ImplItem(item) => {
if matches!(item.kind, ImplItemKind::TyAlias(..)) {
is_associated_type = true;
}
&item.generics
}

Node::Item(item) => {
match item.kind {
Expand Down Expand Up @@ -2070,6 +2083,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
if let Some(_trait_ref) = is_trait {
predicates.extend(tcx.super_predicates_of(def_id).predicates.iter().cloned());
}
debug!("explicit_predicates_of: super predicates = {:?}", predicates);

// In default impls, we can assume that the self type implements
// the trait. So in:
Expand All @@ -2085,6 +2099,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
tcx.def_span(def_id),
));
}
debug!("explicit_predicates_of: default impls = {:?}", predicates);

// Collect the region predicates that were declared inline as
// well. In the case of parameters declared on a fn or method, we
Expand Down Expand Up @@ -2113,6 +2128,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
}
}

debug!("explicit_predicates_of: region predicates = {:?}", predicates);

// Collect the predicates that were written inline by the user on each
// type parameter (e.g., `<T: Foo>`).
for param in ast_generics.params {
Expand All @@ -2132,7 +2149,34 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
sized,
param.span,
);
predicates.extend(bounds.predicates(tcx, param_ty));
debug!("explicit_predicates_of: bounds = {:?}", bounds);

// We need to skip from the predicate list the implicit Sized
// bound for the generic types inside a GAT in order to have recursion (#80626).
// For example, in:
//
// trait Allocator {
// type Allocated<T>;
// }
//
// the GAT implicitly has the bound `Allocated<T>: Sized`, but
// this bound generates a bound `T: Sized`, which we don't want
// because there are type constructors that can be sized without
// a `Sized` restriction on `T` (`Box<T>`, `&T`, `*T`).
// However, we can't just remove the predicates with `Sized`, because
// if the user explicitly annotates `T` as `Sized`
// a trait implementation with `?Sized` could be unsound:
//
// impl Allocator for () {
// type Allocated<T: ?Sized> = Box<T>;
// }
//
// So we just skip the implicit `Sized` predicate on `predicates()`
predicates.extend(bounds.predicates(
tcx,
param_ty,
is_associated_type && bounds.implicitly_sized.is_some(),
));
}
GenericParamKind::Const { .. } => {
// Bounds on const parameters are currently not possible.
Expand All @@ -2142,6 +2186,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
}
}

debug!("explicit_predicates_of: inline predicates = {:?}", predicates);

// Add in the bounds that appear in the where-clause.
let where_clause = &ast_generics.where_clause;
for predicate in where_clause.predicates {
Expand Down Expand Up @@ -2194,7 +2240,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
&mut bounds,
false,
);
predicates.extend(bounds.predicates(tcx, ty));
predicates.extend(bounds.predicates(tcx, ty, false));
}

&hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => {
Expand All @@ -2208,7 +2254,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
ty,
&mut bounds,
);
predicates.extend(bounds.predicates(tcx, ty));
predicates.extend(bounds.predicates(tcx, ty, false));
}

hir::GenericBound::Outlives(lifetime) => {
Expand Down Expand Up @@ -2251,8 +2297,11 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
}
}

debug!("explicit_predicates_of: where predicates = {:?}", predicates);

if tcx.features().const_evaluatable_checked {
predicates.extend(const_evaluatable_predicates_of(tcx, def_id.expect_local()));
debug!("explicit_predicates_of: const predicates = {:?}", predicates);
}

let mut predicates: Vec<_> = predicates.into_iter().collect();
Expand Down Expand Up @@ -2437,7 +2486,7 @@ fn predicates_from_bound<'tcx>(
&mut bounds,
false,
);
bounds.predicates(astconv.tcx(), param_ty)
bounds.predicates(astconv.tcx(), param_ty, false)
}
hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => {
let mut bounds = Bounds::default();
Expand All @@ -2449,7 +2498,7 @@ fn predicates_from_bound<'tcx>(
param_ty,
&mut bounds,
);
bounds.predicates(astconv.tcx(), param_ty)
bounds.predicates(astconv.tcx(), param_ty, false)
}
hir::GenericBound::Outlives(ref lifetime) => {
let region = astconv.ast_region_to_region(lifetime, None);
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_typeck/src/collect/item_bounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ fn associated_type_bounds<'tcx>(
}
});

let all_bounds = tcx
.arena
.alloc_from_iter(bounds.predicates(tcx, item_ty).into_iter().chain(bounds_from_parent));
let all_bounds = tcx.arena.alloc_from_iter(
bounds.predicates(tcx, item_ty, false).into_iter().chain(bounds_from_parent),
);
debug!("associated_type_bounds({}) = {:?}", tcx.def_path_str(assoc_item_def_id), all_bounds);
all_bounds
}
Expand All @@ -73,7 +73,7 @@ fn opaque_type_bounds<'tcx>(
SizedByDefault::Yes,
span,
)
.predicates(tcx, item_ty);
.predicates(tcx, item_ty, false);

debug!("opaque_type_bounds({}) = {:?}", tcx.def_path_str(opaque_def_id), bounds);

Expand Down