Skip to content

Commit ad0d1d7

Browse files
committed
Auto merge of #90076 - jackh726:wherethewhere, r=nikomatsakis
Change location of where clause on GATs Closes #89122 ~Blocked on lang FCP~ r? `@nikomatsakis`
2 parents 5d9d1e8 + d16ec7b commit ad0d1d7

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+552
-283
lines changed

compiler/rustc_ast/src/ast.rs

+27
Original file line numberDiff line numberDiff line change
@@ -2662,10 +2662,37 @@ pub struct Trait {
26622662
pub items: Vec<P<AssocItem>>,
26632663
}
26642664

2665+
/// The location of a where clause on a `TyAlias` (`Span`) and whether there was
2666+
/// a `where` keyword (`bool`). This is split out from `WhereClause`, since there
2667+
/// are two locations for where clause on type aliases, but their predicates
2668+
/// are concatenated together.
2669+
///
2670+
/// Take this example:
2671+
/// ```ignore (only-for-syntax-highlight)
2672+
/// trait Foo {
2673+
/// type Assoc<'a, 'b> where Self: 'a, Self: 'b;
2674+
/// }
2675+
/// impl Foo for () {
2676+
/// type Assoc<'a, 'b> where Self: 'a = () where Self: 'b;
2677+
/// // ^^^^^^^^^^^^^^ first where clause
2678+
/// // ^^^^^^^^^^^^^^ second where clause
2679+
/// }
2680+
/// ```
2681+
///
2682+
/// If there is no where clause, then this is `false` with `DUMMY_SP`.
2683+
#[derive(Copy, Clone, Encodable, Decodable, Debug, Default)]
2684+
pub struct TyAliasWhereClause(pub bool, pub Span);
2685+
26652686
#[derive(Clone, Encodable, Decodable, Debug)]
26662687
pub struct TyAlias {
26672688
pub defaultness: Defaultness,
26682689
pub generics: Generics,
2690+
/// The span information for the two where clauses (before equals, after equals)
2691+
pub where_clauses: (TyAliasWhereClause, TyAliasWhereClause),
2692+
/// The index in `generics.where_clause.predicates` that would split into
2693+
/// predicates from the where clause before the equals and the predicates
2694+
/// from the where clause after the equals
2695+
pub where_predicates_split: usize,
26692696
pub bounds: GenericBounds,
26702697
pub ty: Option<P<Ty>>,
26712698
}

compiler/rustc_ast/src/mut_visit.rs

+25-3
Original file line numberDiff line numberDiff line change
@@ -1018,9 +1018,13 @@ pub fn noop_visit_item_kind<T: MutVisitor>(kind: &mut ItemKind, vis: &mut T) {
10181018
}
10191019
ItemKind::ForeignMod(nm) => vis.visit_foreign_mod(nm),
10201020
ItemKind::GlobalAsm(asm) => noop_visit_inline_asm(asm, vis),
1021-
ItemKind::TyAlias(box TyAlias { defaultness, generics, bounds, ty }) => {
1021+
ItemKind::TyAlias(box TyAlias {
1022+
defaultness, generics, where_clauses, bounds, ty, ..
1023+
}) => {
10221024
visit_defaultness(defaultness, vis);
10231025
vis.visit_generics(generics);
1026+
vis.visit_span(&mut where_clauses.0.1);
1027+
vis.visit_span(&mut where_clauses.1.1);
10241028
visit_bounds(bounds, vis);
10251029
visit_opt(ty, |ty| vis.visit_ty(ty));
10261030
}
@@ -1087,9 +1091,18 @@ pub fn noop_flat_map_assoc_item<T: MutVisitor>(
10871091
visit_fn_sig(sig, visitor);
10881092
visit_opt(body, |body| visitor.visit_block(body));
10891093
}
1090-
AssocItemKind::TyAlias(box TyAlias { defaultness, generics, bounds, ty }) => {
1094+
AssocItemKind::TyAlias(box TyAlias {
1095+
defaultness,
1096+
generics,
1097+
where_clauses,
1098+
bounds,
1099+
ty,
1100+
..
1101+
}) => {
10911102
visit_defaultness(defaultness, visitor);
10921103
visitor.visit_generics(generics);
1104+
visitor.visit_span(&mut where_clauses.0.1);
1105+
visitor.visit_span(&mut where_clauses.1.1);
10931106
visit_bounds(bounds, visitor);
10941107
visit_opt(ty, |ty| visitor.visit_ty(ty));
10951108
}
@@ -1152,9 +1165,18 @@ pub fn noop_flat_map_foreign_item<T: MutVisitor>(
11521165
visit_fn_sig(sig, visitor);
11531166
visit_opt(body, |body| visitor.visit_block(body));
11541167
}
1155-
ForeignItemKind::TyAlias(box TyAlias { defaultness, generics, bounds, ty }) => {
1168+
ForeignItemKind::TyAlias(box TyAlias {
1169+
defaultness,
1170+
generics,
1171+
where_clauses,
1172+
bounds,
1173+
ty,
1174+
..
1175+
}) => {
11561176
visit_defaultness(defaultness, visitor);
11571177
visitor.visit_generics(generics);
1178+
visitor.visit_span(&mut where_clauses.0.1);
1179+
visitor.visit_span(&mut where_clauses.1.1);
11581180
visit_bounds(bounds, visitor);
11591181
visit_opt(ty, |ty| visitor.visit_ty(ty));
11601182
}

compiler/rustc_ast/src/visit.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
303303
walk_list!(visitor, visit_foreign_item, &foreign_module.items);
304304
}
305305
ItemKind::GlobalAsm(ref asm) => walk_inline_asm(visitor, asm),
306-
ItemKind::TyAlias(box TyAlias { defaultness: _, ref generics, ref bounds, ref ty }) => {
306+
ItemKind::TyAlias(box TyAlias { ref generics, ref bounds, ref ty, .. }) => {
307307
visitor.visit_generics(generics);
308308
walk_list!(visitor, visit_param_bound, bounds);
309309
walk_list!(visitor, visit_ty, ty);
@@ -559,7 +559,7 @@ pub fn walk_foreign_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a ForeignI
559559
let kind = FnKind::Fn(FnCtxt::Foreign, ident, sig, vis, body.as_deref());
560560
visitor.visit_fn(kind, span, id);
561561
}
562-
ForeignItemKind::TyAlias(box TyAlias { defaultness: _, generics, bounds, ty }) => {
562+
ForeignItemKind::TyAlias(box TyAlias { generics, bounds, ty, .. }) => {
563563
visitor.visit_generics(generics);
564564
walk_list!(visitor, visit_param_bound, bounds);
565565
walk_list!(visitor, visit_ty, ty);
@@ -665,7 +665,7 @@ pub fn walk_assoc_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem,
665665
let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), ident, sig, vis, body.as_deref());
666666
visitor.visit_fn(kind, span, id);
667667
}
668-
AssocItemKind::TyAlias(box TyAlias { defaultness: _, generics, bounds, ty }) => {
668+
AssocItemKind::TyAlias(box TyAlias { generics, bounds, ty, .. }) => {
669669
visitor.visit_generics(generics);
670670
walk_list!(visitor, visit_param_bound, bounds);
671671
walk_list!(visitor, visit_ty, ty);

compiler/rustc_ast_lowering/src/item.rs

+50-9
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,26 @@ pub(super) struct ItemLowerer<'a, 'lowering, 'hir> {
2525
pub(super) lctx: &'a mut LoweringContext<'lowering, 'hir>,
2626
}
2727

28+
/// When we have a ty alias we *may* have two where clauses. To give the best diagnostics, we set the span
29+
/// to the where clause that is prefered, if it exists. Otherwise, it sets the span to the other where
30+
/// clause if it exists.
31+
fn add_ty_alias_where_clause(
32+
generics: &mut ast::Generics,
33+
mut where_clauses: (TyAliasWhereClause, TyAliasWhereClause),
34+
prefer_first: bool,
35+
) {
36+
if !prefer_first {
37+
where_clauses = (where_clauses.1, where_clauses.0);
38+
}
39+
if where_clauses.0.0 || !where_clauses.1.0 {
40+
generics.where_clause.has_where_token = where_clauses.0.0;
41+
generics.where_clause.span = where_clauses.0.1;
42+
} else {
43+
generics.where_clause.has_where_token = where_clauses.1.0;
44+
generics.where_clause.span = where_clauses.1.1;
45+
}
46+
}
47+
2848
impl ItemLowerer<'_, '_, '_> {
2949
fn with_trait_impl_ref<T>(
3050
&mut self,
@@ -277,7 +297,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
277297
ItemKind::GlobalAsm(ref asm) => {
278298
hir::ItemKind::GlobalAsm(self.lower_inline_asm(span, asm))
279299
}
280-
ItemKind::TyAlias(box TyAlias { ref generics, ty: Some(ref ty), .. }) => {
300+
ItemKind::TyAlias(box TyAlias {
301+
ref generics,
302+
where_clauses,
303+
ty: Some(ref ty),
304+
..
305+
}) => {
281306
// We lower
282307
//
283308
// type Foo = impl Trait
@@ -292,16 +317,22 @@ impl<'hir> LoweringContext<'_, 'hir> {
292317
capturable_lifetimes: &mut FxHashSet::default(),
293318
},
294319
);
320+
let mut generics = generics.clone();
321+
add_ty_alias_where_clause(&mut generics, where_clauses, true);
295322
let generics = self.lower_generics(
296-
generics,
323+
&generics,
297324
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
298325
);
299326
hir::ItemKind::TyAlias(ty, generics)
300327
}
301-
ItemKind::TyAlias(box TyAlias { ref generics, ty: None, .. }) => {
328+
ItemKind::TyAlias(box TyAlias {
329+
ref generics, ref where_clauses, ty: None, ..
330+
}) => {
302331
let ty = self.arena.alloc(self.ty(span, hir::TyKind::Err));
332+
let mut generics = generics.clone();
333+
add_ty_alias_where_clause(&mut generics, *where_clauses, true);
303334
let generics = self.lower_generics(
304-
generics,
335+
&generics,
305336
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
306337
);
307338
hir::ItemKind::TyAlias(ty, generics)
@@ -832,18 +863,26 @@ impl<'hir> LoweringContext<'_, 'hir> {
832863
);
833864
(generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)))
834865
}
835-
AssocItemKind::TyAlias(box TyAlias { ref generics, ref bounds, ref ty, .. }) => {
866+
AssocItemKind::TyAlias(box TyAlias {
867+
ref generics,
868+
where_clauses,
869+
ref bounds,
870+
ref ty,
871+
..
872+
}) => {
836873
let ty = ty.as_ref().map(|x| {
837874
self.lower_ty(x, ImplTraitContext::Disallowed(ImplTraitPosition::Type))
838875
});
876+
let mut generics = generics.clone();
877+
add_ty_alias_where_clause(&mut generics, where_clauses, false);
839878
let generics = self.lower_generics(
840-
generics,
879+
&generics,
841880
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
842881
);
843882
let kind = hir::TraitItemKind::Type(
844883
self.lower_param_bounds(
845884
bounds,
846-
ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
885+
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
847886
),
848887
ty,
849888
);
@@ -917,9 +956,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
917956

918957
(generics, hir::ImplItemKind::Fn(sig, body_id))
919958
}
920-
AssocItemKind::TyAlias(box TyAlias { generics, ty, .. }) => {
959+
AssocItemKind::TyAlias(box TyAlias { generics, where_clauses, ty, .. }) => {
960+
let mut generics = generics.clone();
961+
add_ty_alias_where_clause(&mut generics, *where_clauses, false);
921962
let generics = self.lower_generics(
922-
generics,
963+
&generics,
923964
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
924965
);
925966
let kind = match ty {

compiler/rustc_ast_passes/src/ast_validation.rs

+83-8
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,13 @@ use rustc_ast::ptr::P;
1111
use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
1212
use rustc_ast::walk_list;
1313
use rustc_ast::*;
14-
use rustc_ast_pretty::pprust;
14+
use rustc_ast_pretty::pprust::{self, State};
1515
use rustc_data_structures::fx::FxHashMap;
1616
use rustc_errors::{error_code, pluralize, struct_span_err, Applicability};
1717
use rustc_parse::validate_attr;
18-
use rustc_session::lint::builtin::{MISSING_ABI, PATTERNS_IN_FNS_WITHOUT_BODY};
18+
use rustc_session::lint::builtin::{
19+
DEPRECATED_WHERE_CLAUSE_LOCATION, MISSING_ABI, PATTERNS_IN_FNS_WITHOUT_BODY,
20+
};
1921
use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer};
2022
use rustc_session::Session;
2123
use rustc_span::source_map::Spanned;
@@ -122,6 +124,42 @@ impl<'a> AstValidator<'a> {
122124
}
123125
}
124126

127+
fn check_gat_where(
128+
&mut self,
129+
id: NodeId,
130+
before_predicates: &[WherePredicate],
131+
where_clauses: (ast::TyAliasWhereClause, ast::TyAliasWhereClause),
132+
) {
133+
if !before_predicates.is_empty() {
134+
let mut state = State::new();
135+
if !where_clauses.1.0 {
136+
state.space();
137+
state.word_space("where");
138+
} else {
139+
state.word_space(",");
140+
}
141+
let mut first = true;
142+
for p in before_predicates.iter() {
143+
if !first {
144+
state.word_space(",");
145+
}
146+
first = false;
147+
state.print_where_predicate(p);
148+
}
149+
let suggestion = state.s.eof();
150+
self.lint_buffer.buffer_lint_with_diagnostic(
151+
DEPRECATED_WHERE_CLAUSE_LOCATION,
152+
id,
153+
where_clauses.0.1,
154+
"where clause not allowed here",
155+
BuiltinLintDiagnostics::DeprecatedWhereclauseLocation(
156+
where_clauses.1.1.shrink_to_hi(),
157+
suggestion,
158+
),
159+
);
160+
}
161+
}
162+
125163
fn with_banned_assoc_ty_bound(&mut self, f: impl FnOnce(&mut Self)) {
126164
let old = mem::replace(&mut self.is_assoc_ty_bound_banned, true);
127165
f(self);
@@ -454,7 +492,7 @@ impl<'a> AstValidator<'a> {
454492
.emit();
455493
}
456494

457-
fn check_foreign_ty_genericless(&self, generics: &Generics) {
495+
fn check_foreign_ty_genericless(&self, generics: &Generics, where_span: Span) {
458496
let cannot_have = |span, descr, remove_descr| {
459497
self.err_handler()
460498
.struct_span_err(
@@ -477,7 +515,7 @@ impl<'a> AstValidator<'a> {
477515
}
478516

479517
if !generics.where_clause.predicates.is_empty() {
480-
cannot_have(generics.where_clause.span, "`where` clauses", "`where` clause");
518+
cannot_have(where_span, "`where` clauses", "`where` clause");
481519
}
482520
}
483521

@@ -1223,13 +1261,29 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
12231261
let msg = "free static item without body";
12241262
self.error_item_without_body(item.span, "static", msg, " = <expr>;");
12251263
}
1226-
ItemKind::TyAlias(box TyAlias { defaultness, ref bounds, ref ty, .. }) => {
1264+
ItemKind::TyAlias(box TyAlias {
1265+
defaultness,
1266+
where_clauses,
1267+
ref bounds,
1268+
ref ty,
1269+
..
1270+
}) => {
12271271
self.check_defaultness(item.span, defaultness);
12281272
if ty.is_none() {
12291273
let msg = "free type alias without body";
12301274
self.error_item_without_body(item.span, "type", msg, " = <type>;");
12311275
}
12321276
self.check_type_no_bounds(bounds, "this context");
1277+
if where_clauses.1.0 {
1278+
let mut err = self.err_handler().struct_span_err(
1279+
where_clauses.1.1,
1280+
"where clauses are not allowed after the type for type aliases",
1281+
);
1282+
err.note(
1283+
"see issue #89122 <https://github.com/rust-lang/rust/issues/89122> for more information",
1284+
);
1285+
err.emit();
1286+
}
12331287
}
12341288
_ => {}
12351289
}
@@ -1245,11 +1299,18 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
12451299
self.check_foreign_fn_headerless(fi.ident, fi.span, sig.header);
12461300
self.check_foreign_item_ascii_only(fi.ident);
12471301
}
1248-
ForeignItemKind::TyAlias(box TyAlias { defaultness, generics, bounds, ty, .. }) => {
1302+
ForeignItemKind::TyAlias(box TyAlias {
1303+
defaultness,
1304+
generics,
1305+
where_clauses,
1306+
bounds,
1307+
ty,
1308+
..
1309+
}) => {
12491310
self.check_defaultness(fi.span, *defaultness);
12501311
self.check_foreign_kind_bodyless(fi.ident, "type", ty.as_ref().map(|b| b.span));
12511312
self.check_type_no_bounds(bounds, "`extern` blocks");
1252-
self.check_foreign_ty_genericless(generics);
1313+
self.check_foreign_ty_genericless(generics, where_clauses.0.1);
12531314
self.check_foreign_item_ascii_only(fi.ident);
12541315
}
12551316
ForeignItemKind::Static(_, _, body) => {
@@ -1503,9 +1564,23 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
15031564
AssocItemKind::Fn(box Fn { body, .. }) => {
15041565
self.check_impl_item_provided(item.span, body, "function", " { <body> }");
15051566
}
1506-
AssocItemKind::TyAlias(box TyAlias { bounds, ty, .. }) => {
1567+
AssocItemKind::TyAlias(box TyAlias {
1568+
generics,
1569+
where_clauses,
1570+
where_predicates_split,
1571+
bounds,
1572+
ty,
1573+
..
1574+
}) => {
15071575
self.check_impl_item_provided(item.span, ty, "type", " = <type>;");
15081576
self.check_type_no_bounds(bounds, "`impl`s");
1577+
if ty.is_some() {
1578+
self.check_gat_where(
1579+
item.id,
1580+
generics.where_clause.predicates.split_at(*where_predicates_split).0,
1581+
*where_clauses,
1582+
);
1583+
}
15091584
}
15101585
_ => {}
15111586
}

0 commit comments

Comments
 (0)