Skip to content

Commit

Permalink
Rollup merge of rust-lang#108554 - compiler-errors:late-bound-object-…
Browse files Browse the repository at this point in the history
…default, r=oli-obk

Only look for param in item's generics if it actually comes from generics

Record whether a `hir::GenericParam` comes from an item's generics, or from a `for<...>` binder. Then, only look for the param in `object_lifetime_default` if it actually comes from the item's generics.

Fixes rust-lang#108177
  • Loading branch information
Dylan-DPC committed Feb 28, 2023
2 parents 24018a4 + f851a8a commit c0f9b23
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 49 deletions.
15 changes: 11 additions & 4 deletions compiler/rustc_ast_lowering/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1339,13 +1339,19 @@ impl<'hir> LoweringContext<'_, 'hir> {
.map(|predicate| self.lower_where_predicate(predicate)),
);

let mut params: SmallVec<[hir::GenericParam<'hir>; 4]> =
self.lower_generic_params_mut(&generics.params).collect();
let mut params: SmallVec<[hir::GenericParam<'hir>; 4]> = self
.lower_generic_params_mut(&generics.params, hir::GenericParamSource::Generics)
.collect();

// Introduce extra lifetimes if late resolution tells us to.
let extra_lifetimes = self.resolver.take_extra_lifetime_params(parent_node_id);
params.extend(extra_lifetimes.into_iter().filter_map(|(ident, node_id, res)| {
self.lifetime_res_to_generic_param(ident, node_id, res)
self.lifetime_res_to_generic_param(
ident,
node_id,
res,
hir::GenericParamSource::Generics,
)
}));

let has_where_clause_predicates = !generics.where_clause.predicates.is_empty();
Expand Down Expand Up @@ -1449,7 +1455,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
span,
}) => hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
hir_id: self.next_id(),
bound_generic_params: self.lower_generic_params(bound_generic_params),
bound_generic_params: self
.lower_generic_params(bound_generic_params, hir::GenericParamSource::Binder),
bounded_ty: self
.lower_ty(bounded_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Bound)),
bounds: self.arena.alloc_from_iter(bounds.iter().map(|bound| {
Expand Down
39 changes: 30 additions & 9 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -804,6 +804,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
ident: Ident,
node_id: NodeId,
res: LifetimeRes,
source: hir::GenericParamSource,
) -> Option<hir::GenericParam<'hir>> {
let (name, kind) = match res {
LifetimeRes::Param { .. } => {
Expand Down Expand Up @@ -837,6 +838,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
pure_wrt_drop: false,
kind: hir::GenericParamKind::Lifetime { kind },
colon_span: None,
source,
})
}

Expand All @@ -852,11 +854,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
binder: NodeId,
generic_params: &[GenericParam],
) -> &'hir [hir::GenericParam<'hir>] {
let mut generic_params: Vec<_> = self.lower_generic_params_mut(generic_params).collect();
let mut generic_params: Vec<_> = self
.lower_generic_params_mut(generic_params, hir::GenericParamSource::Binder)
.collect();
let extra_lifetimes = self.resolver.take_extra_lifetime_params(binder);
debug!(?extra_lifetimes);
generic_params.extend(extra_lifetimes.into_iter().filter_map(|(ident, node_id, res)| {
self.lifetime_res_to_generic_param(ident, node_id, res)
self.lifetime_res_to_generic_param(ident, node_id, res, hir::GenericParamSource::Binder)
}));
let generic_params = self.arena.alloc_from_iter(generic_params);
debug!(?generic_params);
Expand Down Expand Up @@ -1375,8 +1379,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
span,
);
let ident = Ident::from_str_and_span(&pprust::ty_to_string(t), span);
let (param, bounds, path) =
self.lower_generic_and_bounds(*def_node_id, span, ident, bounds);
let (param, bounds, path) = self.lower_universal_param_and_bounds(
*def_node_id,
span,
ident,
bounds,
);
self.impl_trait_defs.push(param);
if let Some(bounds) = bounds {
self.impl_trait_bounds.push(bounds);
Expand Down Expand Up @@ -1530,6 +1538,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
pure_wrt_drop: false,
kind: hir::GenericParamKind::Lifetime { kind },
colon_span: None,
source: hir::GenericParamSource::Generics,
}
},
));
Expand Down Expand Up @@ -1987,6 +1996,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
pure_wrt_drop: false,
kind: hir::GenericParamKind::Lifetime { kind },
colon_span: None,
source: hir::GenericParamSource::Generics,
}
},
));
Expand Down Expand Up @@ -2152,16 +2162,25 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
fn lower_generic_params_mut<'s>(
&'s mut self,
params: &'s [GenericParam],
source: hir::GenericParamSource,
) -> impl Iterator<Item = hir::GenericParam<'hir>> + Captures<'a> + Captures<'s> {
params.iter().map(move |param| self.lower_generic_param(param))
params.iter().map(move |param| self.lower_generic_param(param, source))
}

fn lower_generic_params(&mut self, params: &[GenericParam]) -> &'hir [hir::GenericParam<'hir>] {
self.arena.alloc_from_iter(self.lower_generic_params_mut(params))
fn lower_generic_params(
&mut self,
params: &[GenericParam],
source: hir::GenericParamSource,
) -> &'hir [hir::GenericParam<'hir>] {
self.arena.alloc_from_iter(self.lower_generic_params_mut(params, source))
}

#[instrument(level = "trace", skip(self))]
fn lower_generic_param(&mut self, param: &GenericParam) -> hir::GenericParam<'hir> {
fn lower_generic_param(
&mut self,
param: &GenericParam,
source: hir::GenericParamSource,
) -> hir::GenericParam<'hir> {
let (name, kind) = self.lower_generic_param_kind(param);

let hir_id = self.lower_node_id(param.id);
Expand All @@ -2174,6 +2193,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
pure_wrt_drop: self.tcx.sess.contains_name(&param.attrs, sym::may_dangle),
kind,
colon_span: param.colon_span.map(|s| self.lower_span(s)),
source,
}
}

Expand Down Expand Up @@ -2266,7 +2286,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}

#[instrument(level = "debug", skip(self), ret)]
fn lower_generic_and_bounds(
fn lower_universal_param_and_bounds(
&mut self,
node_id: NodeId,
span: Span,
Expand All @@ -2286,6 +2306,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
span,
kind: hir::GenericParamKind::Type { default: None, synthetic: true },
colon_span: None,
source: hir::GenericParamSource::Generics,
};

let preds = self.lower_generic_bound_predicate(
Expand Down
15 changes: 15 additions & 0 deletions compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,7 @@ pub struct GenericParam<'hir> {
pub pure_wrt_drop: bool,
pub kind: GenericParamKind<'hir>,
pub colon_span: Option<Span>,
pub source: GenericParamSource,
}

impl<'hir> GenericParam<'hir> {
Expand All @@ -516,6 +517,20 @@ impl<'hir> GenericParam<'hir> {
}
}

/// Records where the generic parameter originated from.
///
/// This can either be from an item's generics, in which case it's typically
/// early-bound (but can be a late-bound lifetime in functions, for example),
/// or from a `for<...>` binder, in which case it's late-bound (and notably,
/// does not show up in the parent item's generics).
#[derive(Debug, HashStable_Generic, PartialEq, Eq, Copy, Clone)]
pub enum GenericParamSource {
// Early or late-bound parameters defined on an item
Generics,
// Late-bound parameters defined via a `for<...>`
Binder,
}

#[derive(Default)]
pub struct GenericParamCount {
pub lifetimes: usize,
Expand Down
81 changes: 45 additions & 36 deletions compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1034,45 +1034,53 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
fn object_lifetime_default(tcx: TyCtxt<'_>, param_def_id: DefId) -> ObjectLifetimeDefault {
debug_assert_eq!(tcx.def_kind(param_def_id), DefKind::TyParam);
let param_def_id = param_def_id.expect_local();
let parent_def_id = tcx.local_parent(param_def_id);
let generics = tcx.hir().get_generics(parent_def_id).unwrap();
let param_hir_id = tcx.local_def_id_to_hir_id(param_def_id);
let param = generics.params.iter().find(|p| p.hir_id == param_hir_id).unwrap();

// Scan the bounds and where-clauses on parameters to extract bounds
// of the form `T:'a` so as to determine the `ObjectLifetimeDefault`
// for each type parameter.
match param.kind {
GenericParamKind::Type { .. } => {
let mut set = Set1::Empty;

// Look for `type: ...` where clauses.
for bound in generics.bounds_for_param(param_def_id) {
// Ignore `for<'a> type: ...` as they can change what
// lifetimes mean (although we could "just" handle it).
if !bound.bound_generic_params.is_empty() {
continue;
}
let hir::Node::GenericParam(param) = tcx.hir().get_by_def_id(param_def_id) else {
bug!("expected GenericParam for object_lifetime_default");
};
match param.source {
hir::GenericParamSource::Generics => {
let parent_def_id = tcx.local_parent(param_def_id);
let generics = tcx.hir().get_generics(parent_def_id).unwrap();
let param_hir_id = tcx.local_def_id_to_hir_id(param_def_id);
let param = generics.params.iter().find(|p| p.hir_id == param_hir_id).unwrap();

// Scan the bounds and where-clauses on parameters to extract bounds
// of the form `T:'a` so as to determine the `ObjectLifetimeDefault`
// for each type parameter.
match param.kind {
GenericParamKind::Type { .. } => {
let mut set = Set1::Empty;

// Look for `type: ...` where clauses.
for bound in generics.bounds_for_param(param_def_id) {
// Ignore `for<'a> type: ...` as they can change what
// lifetimes mean (although we could "just" handle it).
if !bound.bound_generic_params.is_empty() {
continue;
}

for bound in bound.bounds {
if let hir::GenericBound::Outlives(lifetime) = bound {
set.insert(lifetime.res);
for bound in bound.bounds {
if let hir::GenericBound::Outlives(lifetime) = bound {
set.insert(lifetime.res);
}
}
}
}
}

match set {
Set1::Empty => ObjectLifetimeDefault::Empty,
Set1::One(hir::LifetimeName::Static) => ObjectLifetimeDefault::Static,
Set1::One(hir::LifetimeName::Param(param_def_id)) => {
ObjectLifetimeDefault::Param(param_def_id.to_def_id())
match set {
Set1::Empty => ObjectLifetimeDefault::Empty,
Set1::One(hir::LifetimeName::Static) => ObjectLifetimeDefault::Static,
Set1::One(hir::LifetimeName::Param(param_def_id)) => {
ObjectLifetimeDefault::Param(param_def_id.to_def_id())
}
_ => ObjectLifetimeDefault::Ambiguous,
}
}
_ => {
bug!("object_lifetime_default_raw must only be called on a type parameter")
}
_ => ObjectLifetimeDefault::Ambiguous,
}
}
_ => {
bug!("object_lifetime_default_raw must only be called on a type parameter")
}
hir::GenericParamSource::Binder => ObjectLifetimeDefault::Empty,
}
}

Expand Down Expand Up @@ -1392,9 +1400,10 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
return;
}

self.tcx
.sess
.delay_span_bug(self.tcx.hir().span(hir_id), "could not resolve {param_def_id:?}");
self.tcx.sess.delay_span_bug(
self.tcx.hir().span(hir_id),
format!("could not resolve {param_def_id:?}"),
);
}

#[instrument(level = "debug", skip(self))]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// check-pass
// compile-flags: --crate-type=lib

#![feature(non_lifetime_binders)]
//~^ WARN the feature `non_lifetime_binders` is incomplete

pub fn f<T>() where for<U> (T, U): Copy {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/object-lifetime-default-for-late.rs:4:12
|
LL | #![feature(non_lifetime_binders)]
| ^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
= note: `#[warn(incomplete_features)]` on by default

warning: 1 warning emitted

0 comments on commit c0f9b23

Please sign in to comment.