Skip to content

Commit f1f1d56

Browse files
committed
Don't move ?Trait bounds to param bounds if they're in where clauses
1 parent 2eaf9fe commit f1f1d56

File tree

12 files changed

+103
-82
lines changed

12 files changed

+103
-82
lines changed

compiler/rustc_ast_lowering/src/item.rs

+16-30
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ use super::{AnonymousLifetimeMode, LoweringContext, ParamMode};
22
use super::{ImplTraitContext, ImplTraitPosition};
33
use crate::Arena;
44

5-
use rustc_ast::node_id::NodeMap;
65
use rustc_ast::ptr::P;
76
use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
87
use rustc_ast::*;
@@ -1351,8 +1350,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
13511350
generics: &Generics,
13521351
itctx: ImplTraitContext<'_, 'hir>,
13531352
) -> GenericsCtor<'hir> {
1354-
// Collect `?Trait` bounds in where clause and move them to parameter definitions.
1355-
let mut add_bounds: NodeMap<Vec<_>> = Default::default();
1353+
// Error if `?Trait` bounds in where clauses don't refer directly to type paramters.
1354+
// Note: we used to clone these bounds directly onto the type parameter (and avoid lowering
1355+
// these into hir when we lower thee where clauses), but this makes it quite difficult to
1356+
// keep track of the Span info. Now, `is_unsized` in `AstConv` checks both param bounds and
1357+
// where clauses for `?Sized`.
13561358
for pred in &generics.where_clause.predicates {
13571359
if let WherePredicate::BoundPredicate(ref bound_pred) = *pred {
13581360
'next_bound: for bound in &bound_pred.bounds {
@@ -1368,7 +1370,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
13681370
{
13691371
for param in &generics.params {
13701372
if def_id == self.resolver.local_def_id(param.id).to_def_id() {
1371-
add_bounds.entry(param.id).or_default().push(bound.clone());
13721373
continue 'next_bound;
13731374
}
13741375
}
@@ -1386,7 +1387,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
13861387
}
13871388

13881389
GenericsCtor {
1389-
params: self.lower_generic_params_mut(&generics.params, &add_bounds, itctx).collect(),
1390+
params: self.lower_generic_params_mut(&generics.params, itctx).collect(),
13901391
where_clause: self.lower_where_clause(&generics.where_clause),
13911392
span: self.lower_span(generics.span),
13921393
}
@@ -1419,32 +1420,17 @@ impl<'hir> LoweringContext<'_, 'hir> {
14191420
ref bounded_ty,
14201421
ref bounds,
14211422
span,
1422-
}) => {
1423-
self.with_in_scope_lifetime_defs(&bound_generic_params, |this| {
1424-
hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
1425-
bound_generic_params: this.lower_generic_params(
1426-
bound_generic_params,
1427-
&NodeMap::default(),
1428-
ImplTraitContext::disallowed(),
1429-
),
1430-
bounded_ty: this.lower_ty(bounded_ty, ImplTraitContext::disallowed()),
1431-
bounds: this.arena.alloc_from_iter(bounds.iter().map(
1432-
|bound| match bound {
1433-
// We used to ignore `?Trait` bounds, as they were copied into type
1434-
// parameters already, but we need to keep them around only for
1435-
// diagnostics when we suggest removal of `?Sized` bounds. See
1436-
// `suggest_constraining_type_param`. This will need to change if
1437-
// we ever allow something *other* than `?Sized`.
1438-
GenericBound::Trait(p, TraitBoundModifier::Maybe) => {
1439-
hir::GenericBound::Unsized(this.lower_span(p.span))
1440-
}
1441-
_ => this.lower_param_bound(bound, ImplTraitContext::disallowed()),
1442-
},
1443-
)),
1444-
span: this.lower_span(span),
1445-
})
1423+
}) => self.with_in_scope_lifetime_defs(&bound_generic_params, |this| {
1424+
hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
1425+
bound_generic_params: this
1426+
.lower_generic_params(bound_generic_params, ImplTraitContext::disallowed()),
1427+
bounded_ty: this.lower_ty(bounded_ty, ImplTraitContext::disallowed()),
1428+
bounds: this.arena.alloc_from_iter(bounds.iter().map(|bound| {
1429+
this.lower_param_bound(bound, ImplTraitContext::disallowed())
1430+
})),
1431+
span: this.lower_span(span),
14461432
})
1447-
}
1433+
}),
14481434
WherePredicate::RegionPredicate(WhereRegionPredicate {
14491435
ref lifetime,
14501436
ref bounds,

compiler/rustc_ast_lowering/src/lib.rs

+5-20
Original file line numberDiff line numberDiff line change
@@ -1313,7 +1313,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
13131313
hir::TyKind::BareFn(this.arena.alloc(hir::BareFnTy {
13141314
generic_params: this.lower_generic_params(
13151315
&f.generic_params,
1316-
&NodeMap::default(),
13171316
ImplTraitContext::disallowed(),
13181317
),
13191318
unsafety: this.lower_unsafety(f.unsafety),
@@ -1998,30 +1997,25 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
19981997
fn lower_generic_params_mut<'s>(
19991998
&'s mut self,
20001999
params: &'s [GenericParam],
2001-
add_bounds: &'s NodeMap<Vec<GenericBound>>,
20022000
mut itctx: ImplTraitContext<'s, 'hir>,
20032001
) -> impl Iterator<Item = hir::GenericParam<'hir>> + Captures<'a> + Captures<'s> {
2004-
params
2005-
.iter()
2006-
.map(move |param| self.lower_generic_param(param, add_bounds, itctx.reborrow()))
2002+
params.iter().map(move |param| self.lower_generic_param(param, itctx.reborrow()))
20072003
}
20082004

20092005
fn lower_generic_params(
20102006
&mut self,
20112007
params: &[GenericParam],
2012-
add_bounds: &NodeMap<Vec<GenericBound>>,
20132008
itctx: ImplTraitContext<'_, 'hir>,
20142009
) -> &'hir [hir::GenericParam<'hir>] {
2015-
self.arena.alloc_from_iter(self.lower_generic_params_mut(params, add_bounds, itctx))
2010+
self.arena.alloc_from_iter(self.lower_generic_params_mut(params, itctx))
20162011
}
20172012

20182013
fn lower_generic_param(
20192014
&mut self,
20202015
param: &GenericParam,
2021-
add_bounds: &NodeMap<Vec<GenericBound>>,
20222016
mut itctx: ImplTraitContext<'_, 'hir>,
20232017
) -> hir::GenericParam<'hir> {
2024-
let mut bounds: Vec<_> = self
2018+
let bounds: Vec<_> = self
20252019
.with_anonymous_lifetime_mode(AnonymousLifetimeMode::ReportError, |this| {
20262020
this.lower_param_bounds_mut(&param.bounds, itctx.reborrow()).collect()
20272021
});
@@ -2057,12 +2051,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
20572051
(param_name, kind)
20582052
}
20592053
GenericParamKind::Type { ref default, .. } => {
2060-
let add_bounds = add_bounds.get(&param.id).map_or(&[][..], |x| &x);
2061-
if !add_bounds.is_empty() {
2062-
let params = self.lower_param_bounds_mut(add_bounds, itctx.reborrow());
2063-
bounds.extend(params);
2064-
}
2065-
20662054
let kind = hir::GenericParamKind::Type {
20672055
default: default.as_ref().map(|x| {
20682056
self.lower_ty(x, ImplTraitContext::Disallowed(ImplTraitPosition::Other))
@@ -2123,11 +2111,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
21232111
p: &PolyTraitRef,
21242112
mut itctx: ImplTraitContext<'_, 'hir>,
21252113
) -> hir::PolyTraitRef<'hir> {
2126-
let bound_generic_params = self.lower_generic_params(
2127-
&p.bound_generic_params,
2128-
&NodeMap::default(),
2129-
itctx.reborrow(),
2130-
);
2114+
let bound_generic_params =
2115+
self.lower_generic_params(&p.bound_generic_params, itctx.reborrow());
21312116

21322117
let trait_ref = self.with_in_scope_lifetime_defs(&p.bound_generic_params, |this| {
21332118
// Any impl Trait types defined within this scope can capture

compiler/rustc_hir/src/hir.rs

-2
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,6 @@ pub enum GenericBound<'hir> {
441441
Trait(PolyTraitRef<'hir>, TraitBoundModifier),
442442
// FIXME(davidtwco): Introduce `PolyTraitRef::LangItem`
443443
LangItemTrait(LangItem, Span, HirId, &'hir GenericArgs<'hir>),
444-
Unsized(Span),
445444
Outlives(Lifetime),
446445
}
447446

@@ -461,7 +460,6 @@ impl GenericBound<'_> {
461460
GenericBound::Trait(t, ..) => t.span,
462461
GenericBound::LangItemTrait(_, span, ..) => *span,
463462
GenericBound::Outlives(l) => l.span,
464-
GenericBound::Unsized(span) => *span,
465463
}
466464
}
467465
}

compiler/rustc_hir/src/intravisit.rs

-1
Original file line numberDiff line numberDiff line change
@@ -871,7 +871,6 @@ pub fn walk_param_bound<'v, V: Visitor<'v>>(visitor: &mut V, bound: &'v GenericB
871871
visitor.visit_generic_args(span, args);
872872
}
873873
GenericBound::Outlives(ref lifetime) => visitor.visit_lifetime(lifetime),
874-
GenericBound::Unsized(_) => {}
875874
}
876875
}
877876

compiler/rustc_hir_pretty/src/lib.rs

-3
Original file line numberDiff line numberDiff line change
@@ -2232,9 +2232,6 @@ impl<'a> State<'a> {
22322232
GenericBound::Outlives(lt) => {
22332233
self.print_lifetime(lt);
22342234
}
2235-
GenericBound::Unsized(_) => {
2236-
self.s.word("?Sized");
2237-
}
22382235
}
22392236
}
22402237
}

compiler/rustc_middle/src/ty/diagnostics.rs

+3-9
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
33
use crate::ty::TyKind::*;
44
use crate::ty::{InferTy, TyCtxt, TyS};
5-
use rustc_data_structures::fx::FxHashSet;
65
use rustc_errors::{Applicability, DiagnosticBuilder};
76
use rustc_hir as hir;
87
use rustc_hir::def_id::DefId;
@@ -114,10 +113,8 @@ fn suggest_removing_unsized_bound(
114113
def_id: Option<DefId>,
115114
) {
116115
// See if there's a `?Sized` bound that can be removed to suggest that.
117-
// First look at the `where` clause because we can have `where T: ?Sized`, but that
118-
// `?Sized` bound is *also* included in the `GenericParam` as a bound, which breaks
119-
// the spans. Hence the somewhat involved logic that follows.
120-
let mut where_unsized_bounds = FxHashSet::default();
116+
// First look at the `where` clause because we can have `where T: ?Sized`,
117+
// then look at params.
121118
for (where_pos, predicate) in generics.where_clause.predicates.iter().enumerate() {
122119
match predicate {
123120
WherePredicate::BoundPredicate(WhereBoundPredicate {
@@ -140,7 +137,6 @@ fn suggest_removing_unsized_bound(
140137
}) if segment.ident.as_str() == param_name => {
141138
for (pos, bound) in bounds.iter().enumerate() {
142139
match bound {
143-
hir::GenericBound::Unsized(_) => {}
144140
hir::GenericBound::Trait(poly, hir::TraitBoundModifier::Maybe)
145141
if poly.trait_ref.trait_def_id() == def_id => {}
146142
_ => continue,
@@ -173,7 +169,6 @@ fn suggest_removing_unsized_bound(
173169
// ^^^^^^^^^
174170
(_, pos, _, _) => bounds[pos - 1].span().shrink_to_hi().to(bound.span()),
175171
};
176-
where_unsized_bounds.insert(bound.span());
177172
err.span_suggestion_verbose(
178173
sp,
179174
"consider removing the `?Sized` bound to make the \
@@ -189,8 +184,7 @@ fn suggest_removing_unsized_bound(
189184
for (pos, bound) in param.bounds.iter().enumerate() {
190185
match bound {
191186
hir::GenericBound::Trait(poly, hir::TraitBoundModifier::Maybe)
192-
if poly.trait_ref.trait_def_id() == def_id
193-
&& !where_unsized_bounds.contains(&bound.span()) =>
187+
if poly.trait_ref.trait_def_id() == def_id =>
194188
{
195189
let sp = match (param.bounds.len(), pos) {
196190
// T: ?Sized,

compiler/rustc_save_analysis/src/dump_visitor.rs

-1
Original file line numberDiff line numberDiff line change
@@ -693,7 +693,6 @@ impl<'tcx> DumpVisitor<'tcx> {
693693
(Some(self.tcx.require_lang_item(lang_item, Some(span))), span)
694694
}
695695
hir::GenericBound::Outlives(..) => continue,
696-
hir::GenericBound::Unsized(_) => continue,
697696
};
698697

699698
if let Some(id) = def_id {

compiler/rustc_typeck/src/astconv/mod.rs

+58-9
Original file line numberDiff line numberDiff line change
@@ -854,7 +854,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
854854
}
855855

856856
// Returns `true` if a bounds list includes `?Sized`.
857-
pub fn is_unsized(&self, ast_bounds: &[hir::GenericBound<'_>], span: Span) -> bool {
857+
fn is_unsized(
858+
&self,
859+
ast_bounds: &[hir::GenericBound<'_>],
860+
self_ty: Option<hir::HirId>,
861+
where_clause: Option<&[hir::WherePredicate<'_>]>,
862+
span: Span,
863+
) -> bool {
858864
let tcx = self.tcx();
859865

860866
// Try to find an unbound in bounds.
@@ -868,11 +874,38 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
868874
}
869875
}
870876
}
877+
if let (Some(self_ty), Some(where_clause)) = (self_ty, where_clause) {
878+
let self_ty_def_id = tcx.hir().local_def_id(self_ty).to_def_id();
879+
for clause in where_clause {
880+
match clause {
881+
hir::WherePredicate::BoundPredicate(pred) => {
882+
match pred.bounded_ty.kind {
883+
hir::TyKind::Path(hir::QPath::Resolved(_, path)) => match path.res {
884+
Res::Def(DefKind::TyParam, def_id) if def_id == self_ty_def_id => {}
885+
_ => continue,
886+
},
887+
_ => continue,
888+
}
889+
for ab in pred.bounds {
890+
if let hir::GenericBound::Trait(ptr, hir::TraitBoundModifier::Maybe) =
891+
ab
892+
{
893+
if unbound.is_none() {
894+
unbound = Some(&ptr.trait_ref);
895+
} else {
896+
tcx.sess.emit_err(MultipleRelaxedDefaultBounds { span });
897+
}
898+
}
899+
}
900+
}
901+
_ => {}
902+
}
903+
}
904+
}
871905

872906
let kind_id = tcx.lang_items().require(LangItem::Sized);
873907
match unbound {
874908
Some(tpb) => {
875-
// FIXME(#8559) currently requires the unbound to be built-in.
876909
if let Ok(kind_id) = kind_id {
877910
if tpb.path.res != Res::Def(DefKind::Trait, kind_id) {
878911
tcx.sess.span_warn(
@@ -940,8 +973,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
940973
false,
941974
);
942975
}
943-
hir::GenericBound::Trait(_, hir::TraitBoundModifier::Maybe)
944-
| hir::GenericBound::Unsized(_) => {}
976+
hir::GenericBound::Trait(_, hir::TraitBoundModifier::Maybe) => {}
945977
hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => self
946978
.instantiate_lang_item_trait_ref(
947979
lang_item, span, hir_id, args, param_ty, bounds,
@@ -970,22 +1002,33 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
9701002
/// example above, but is not true in supertrait listings like `trait Foo: Bar + Baz`.
9711003
///
9721004
/// `span` should be the declaration size of the parameter.
973-
pub fn compute_bounds(
1005+
pub(crate) fn compute_bounds(
9741006
&self,
9751007
param_ty: Ty<'tcx>,
9761008
ast_bounds: &[hir::GenericBound<'_>],
1009+
self_ty: Option<hir::HirId>,
1010+
where_clause: Option<&[hir::WherePredicate<'_>]>,
9771011
sized_by_default: SizedByDefault,
9781012
span: Span,
9791013
) -> Bounds<'tcx> {
980-
self.compute_bounds_inner(param_ty, &ast_bounds, sized_by_default, span)
1014+
self.compute_bounds_inner(
1015+
param_ty,
1016+
&ast_bounds,
1017+
self_ty,
1018+
where_clause,
1019+
sized_by_default,
1020+
span,
1021+
)
9811022
}
9821023

9831024
/// Convert the bounds in `ast_bounds` that refer to traits which define an associated type
9841025
/// named `assoc_name` into ty::Bounds. Ignore the rest.
985-
pub fn compute_bounds_that_match_assoc_type(
1026+
pub(crate) fn compute_bounds_that_match_assoc_type(
9861027
&self,
9871028
param_ty: Ty<'tcx>,
9881029
ast_bounds: &[hir::GenericBound<'_>],
1030+
self_ty: Option<hir::HirId>,
1031+
where_clause: Option<&[hir::WherePredicate<'_>]>,
9891032
sized_by_default: SizedByDefault,
9901033
span: Span,
9911034
assoc_name: Ident,
@@ -1002,13 +1045,15 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
10021045
}
10031046
}
10041047

1005-
self.compute_bounds_inner(param_ty, &result, sized_by_default, span)
1048+
self.compute_bounds_inner(param_ty, &result, self_ty, where_clause, sized_by_default, span)
10061049
}
10071050

10081051
fn compute_bounds_inner(
10091052
&self,
10101053
param_ty: Ty<'tcx>,
10111054
ast_bounds: &[hir::GenericBound<'_>],
1055+
self_ty: Option<hir::HirId>,
1056+
where_clause: Option<&[hir::WherePredicate<'_>]>,
10121057
sized_by_default: SizedByDefault,
10131058
span: Span,
10141059
) -> Bounds<'tcx> {
@@ -1017,7 +1062,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
10171062
self.add_bounds(param_ty, ast_bounds, &mut bounds, ty::List::empty());
10181063

10191064
bounds.implicitly_sized = if let SizedByDefault::Yes = sized_by_default {
1020-
if !self.is_unsized(ast_bounds, span) { Some(span) } else { None }
1065+
if !self.is_unsized(ast_bounds, self_ty, where_clause, span) {
1066+
Some(span)
1067+
} else {
1068+
None
1069+
}
10211070
} else {
10221071
None
10231072
};

0 commit comments

Comments
 (0)