Skip to content

Commit 7c55c99

Browse files
authored
Rollup merge of rust-lang#101807 - jackh726:no-gat-defaults, r=lcnr
Disallow defaults on type GATs Fixes rust-lang#99205
2 parents 4c64c14 + d657d1f commit 7c55c99

File tree

3 files changed

+96
-19
lines changed

3 files changed

+96
-19
lines changed

compiler/rustc_typeck/src/collect.rs

+42-19
Original file line numberDiff line numberDiff line change
@@ -1606,6 +1606,13 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
16061606
_ => None,
16071607
};
16081608

1609+
enum Defaults {
1610+
Allowed,
1611+
// See #36887
1612+
FutureCompatDisallowed,
1613+
Deny,
1614+
}
1615+
16091616
let no_generics = hir::Generics::empty();
16101617
let ast_generics = node.generics().unwrap_or(&no_generics);
16111618
let (opt_self, allow_defaults) = match node {
@@ -1627,17 +1634,26 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
16271634
},
16281635
});
16291636

1630-
(opt_self, true)
1637+
(opt_self, Defaults::Allowed)
16311638
}
16321639
ItemKind::TyAlias(..)
16331640
| ItemKind::Enum(..)
16341641
| ItemKind::Struct(..)
16351642
| ItemKind::OpaqueTy(..)
1636-
| ItemKind::Union(..) => (None, true),
1637-
_ => (None, false),
1643+
| ItemKind::Union(..) => (None, Defaults::Allowed),
1644+
_ => (None, Defaults::FutureCompatDisallowed),
16381645
}
16391646
}
1640-
_ => (None, false),
1647+
1648+
// GATs
1649+
Node::TraitItem(item) if matches!(item.kind, TraitItemKind::Type(..)) => {
1650+
(None, Defaults::Deny)
1651+
}
1652+
Node::ImplItem(item) if matches!(item.kind, ImplItemKind::TyAlias(..)) => {
1653+
(None, Defaults::Deny)
1654+
}
1655+
1656+
_ => (None, Defaults::FutureCompatDisallowed),
16411657
};
16421658

16431659
let has_self = opt_self.is_some();
@@ -1670,23 +1686,30 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
16701686
let type_start = own_start - has_self as u32 + params.len() as u32;
16711687
let mut i = 0;
16721688

1689+
const TYPE_DEFAULT_NOT_ALLOWED: &'static str = "defaults for type parameters are only allowed in \
1690+
`struct`, `enum`, `type`, or `trait` definitions";
1691+
16731692
params.extend(ast_generics.params.iter().filter_map(|param| match param.kind {
16741693
GenericParamKind::Lifetime { .. } => None,
16751694
GenericParamKind::Type { ref default, synthetic, .. } => {
1676-
if !allow_defaults && default.is_some() {
1677-
if !tcx.features().default_type_parameter_fallback {
1678-
tcx.struct_span_lint_hir(
1679-
lint::builtin::INVALID_TYPE_PARAM_DEFAULT,
1680-
param.hir_id,
1681-
param.span,
1682-
|lint| {
1683-
lint.build(
1684-
"defaults for type parameters are only allowed in \
1685-
`struct`, `enum`, `type`, or `trait` definitions",
1686-
)
1687-
.emit();
1688-
},
1689-
);
1695+
if default.is_some() {
1696+
match allow_defaults {
1697+
Defaults::Allowed => {}
1698+
Defaults::FutureCompatDisallowed
1699+
if tcx.features().default_type_parameter_fallback => {}
1700+
Defaults::FutureCompatDisallowed => {
1701+
tcx.struct_span_lint_hir(
1702+
lint::builtin::INVALID_TYPE_PARAM_DEFAULT,
1703+
param.hir_id,
1704+
param.span,
1705+
|lint| {
1706+
lint.build(TYPE_DEFAULT_NOT_ALLOWED).emit();
1707+
},
1708+
);
1709+
}
1710+
Defaults::Deny => {
1711+
tcx.sess.span_err(param.span, TYPE_DEFAULT_NOT_ALLOWED);
1712+
}
16901713
}
16911714
}
16921715

@@ -1703,7 +1726,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
17031726
Some(param_def)
17041727
}
17051728
GenericParamKind::Const { default, .. } => {
1706-
if !allow_defaults && default.is_some() {
1729+
if !matches!(allow_defaults, Defaults::Allowed) && default.is_some() {
17071730
tcx.sess.span_err(
17081731
param.span,
17091732
"defaults for const parameters are only allowed in \
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Check that we disallow GAT param defaults, even with `invalid_type_param_default` allowed
2+
3+
#![allow(invalid_type_param_default)]
4+
5+
trait Trait {
6+
type Assoc<T = u32>;
7+
//~^ defaults for type parameters are only allowed
8+
}
9+
10+
impl Trait for () {
11+
type Assoc<T = u32> = u64;
12+
//~^ defaults for type parameters are only allowed
13+
}
14+
15+
impl Trait for u32 {
16+
type Assoc<T = u32> = T;
17+
//~^ defaults for type parameters are only allowed
18+
}
19+
20+
trait Other {}
21+
impl Other for u32 {}
22+
23+
fn foo<T>()
24+
where
25+
T: Trait<Assoc = u32>,
26+
T::Assoc: Other {
27+
}
28+
29+
fn main() {
30+
// errors
31+
foo::<()>();
32+
// works
33+
foo::<u32>();
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
2+
--> $DIR/type-param-defaults.rs:6:16
3+
|
4+
LL | type Assoc<T = u32>;
5+
| ^^^^^^^
6+
7+
error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
8+
--> $DIR/type-param-defaults.rs:11:16
9+
|
10+
LL | type Assoc<T = u32> = u64;
11+
| ^^^^^^^
12+
13+
error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
14+
--> $DIR/type-param-defaults.rs:16:16
15+
|
16+
LL | type Assoc<T = u32> = T;
17+
| ^^^^^^^
18+
19+
error: aborting due to 3 previous errors
20+

0 commit comments

Comments
 (0)