Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit fde4556

Browse files
committed
Properly check constrainedness of gen params in the presence of weak alias types
1 parent 8677d64 commit fde4556

File tree

9 files changed

+105
-17
lines changed

9 files changed

+105
-17
lines changed

‎compiler/rustc_hir_analysis/src/collect/predicates_of.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
307307
tcx,
308308
&mut predicates,
309309
trait_ref,
310-
&mut cgp::parameters_for_impl(self_ty, trait_ref),
310+
&mut cgp::parameters_for_impl(tcx,self_ty, trait_ref),
311311
);
312312
}
313313

‎compiler/rustc_hir_analysis/src/constrained_generic_params.rs‎

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use rustc_data_structures::fx::FxHashSet;
2+
use rustc_data_structures::stack::ensure_sufficient_stack;
23
use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
34
use rustc_middle::ty::{self, Ty, TyCtxt};
45
use rustc_span::Span;
@@ -27,12 +28,13 @@ impl From<ty::ParamConst> for Parameter {
2728

2829
/// Returns the set of parameters constrained by the impl header.
2930
pub fn parameters_for_impl<'tcx>(
31+
tcx: TyCtxt<'tcx>,
3032
impl_self_ty: Ty<'tcx>,
3133
impl_trait_ref: Option<ty::TraitRef<'tcx>>,
3234
) -> FxHashSet<Parameter> {
3335
let vec = match impl_trait_ref {
34-
Some(tr) => parameters_for(&tr, false),
35-
None => parameters_for(&impl_self_ty, false),
36+
Some(tr) => parameters_for(tcx,&tr, false),
37+
None => parameters_for(tcx,&impl_self_ty, false),
3638
};
3739
vec.into_iter().collect()
3840
}
@@ -43,26 +45,47 @@ pub fn parameters_for_impl<'tcx>(
4345
/// of parameters whose values are needed in order to constrain `ty` - these
4446
/// differ, with the latter being a superset, in the presence of projections.
4547
pub fn parameters_for<'tcx>(
48+
tcx: TyCtxt<'tcx>,
4649
t: &impl TypeVisitable<TyCtxt<'tcx>>,
4750
include_nonconstraining: bool,
4851
) -> Vec<Parameter> {
49-
let mut collector = ParameterCollector { parameters: vec![], include_nonconstraining };
52+
let mut collector =
53+
ParameterCollector { tcx, parameters: vec![], include_nonconstraining, depth: 0 };
5054
t.visit_with(&mut collector);
5155
collector.parameters
5256
}
5357

54-
struct ParameterCollector {
58+
struct ParameterCollector<'tcx> {
59+
tcx: TyCtxt<'tcx>,
5560
parameters: Vec<Parameter>,
5661
include_nonconstraining: bool,
62+
depth: usize,
5763
}
5864

59-
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ParameterCollector {
65+
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ParameterCollector<'tcx> {
6066
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
6167
match *t.kind() {
62-
ty::Alias(..) if !self.include_nonconstraining => {
63-
// projections are not injective
68+
ty::Alias(ty::Projection | ty::Inherent | ty::Opaque, _)
69+
if !self.include_nonconstraining =>
70+
{
71+
// Projections are not injective in general.
6472
return ControlFlow::Continue(());
6573
}
74+
ty::Alias(ty::Weak, alias) if !self.include_nonconstraining => {
75+
if !self.tcx.recursion_limit().value_within_limit(self.depth) {
76+
// Other constituent types may still constrain some generic params, consider
77+
// `<T> (Overflow, T)` for example. Therefore we want to continue instead of
78+
// breaking. Only affects diagnostics.
79+
return ControlFlow::Continue(());
80+
}
81+
self.depth += 1;
82+
return ensure_sufficient_stack(|| {
83+
self.tcx
84+
.type_of(alias.def_id)
85+
.instantiate(self.tcx, alias.args)
86+
.visit_with(self)
87+
});
88+
}
6689
ty::Param(data) => {
6790
self.parameters.push(Parameter::from(data));
6891
}
@@ -82,7 +105,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ParameterCollector {
82105
fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
83106
match c.kind() {
84107
ty::ConstKind::Unevaluated(..) if !self.include_nonconstraining => {
85-
// Constant expressions are not injective
108+
// Constant expressions are not injective in general.
86109
return c.ty().visit_with(self);
87110
}
88111
ty::ConstKind::Param(data) => {
@@ -201,12 +224,12 @@ pub fn setup_constraining_predicates<'tcx>(
201224
// `<<T as Bar>::Baz as Iterator>::Output = <U as Iterator>::Output`
202225
// Then the projection only applies if `T` is known, but it still
203226
// does not determine `U`.
204-
let inputs = parameters_for(&projection.projection_ty, true);
227+
let inputs = parameters_for(tcx,&projection.projection_ty, true);
205228
let relies_only_on_inputs = inputs.iter().all(|p| input_parameters.contains(p));
206229
if !relies_only_on_inputs {
207230
continue;
208231
}
209-
input_parameters.extend(parameters_for(&projection.term, false));
232+
input_parameters.extend(parameters_for(tcx,&projection.term, false));
210233
} else {
211234
continue;
212235
}

‎compiler/rustc_hir_analysis/src/impl_wf_check.rs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ fn enforce_impl_params_are_constrained(
9494
let impl_predicates = tcx.predicates_of(impl_def_id);
9595
let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).map(ty::EarlyBinder::instantiate_identity);
9696

97-
let mut input_parameters = cgp::parameters_for_impl(impl_self_ty, impl_trait_ref);
97+
let mut input_parameters = cgp::parameters_for_impl(tcx,impl_self_ty, impl_trait_ref);
9898
cgp::identify_constrained_generic_params(
9999
tcx,
100100
impl_predicates,
@@ -111,7 +111,7 @@ fn enforce_impl_params_are_constrained(
111111
match item.kind {
112112
ty::AssocKind::Type => {
113113
if item.defaultness(tcx).has_value() {
114-
cgp::parameters_for(&tcx.type_of(def_id).instantiate_identity(), true)
114+
cgp::parameters_for(tcx,&tcx.type_of(def_id).instantiate_identity(), true)
115115
} else {
116116
vec![]
117117
}

‎compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -266,15 +266,15 @@ fn unconstrained_parent_impl_args<'tcx>(
266266
continue;
267267
}
268268

269-
unconstrained_parameters.extend(cgp::parameters_for(&projection_ty, true));
269+
unconstrained_parameters.extend(cgp::parameters_for(tcx,&projection_ty, true));
270270

271-
for param in cgp::parameters_for(&projected_ty, false) {
271+
for param in cgp::parameters_for(tcx,&projected_ty, false) {
272272
if !unconstrained_parameters.contains(&param) {
273273
constrained_params.insert(param.0);
274274
}
275275
}
276276

277-
unconstrained_parameters.extend(cgp::parameters_for(&projected_ty, true));
277+
unconstrained_parameters.extend(cgp::parameters_for(tcx,&projected_ty, true));
278278
}
279279
}
280280

@@ -312,7 +312,7 @@ fn check_duplicate_params<'tcx>(
312312
parent_args: &Vec<GenericArg<'tcx>>,
313313
span: Span,
314314
) -> Result<(), ErrorGuaranteed> {
315-
let mut base_params = cgp::parameters_for(parent_args, true);
315+
let mut base_params = cgp::parameters_for(tcx,parent_args, true);
316316
base_params.sort_by_key(|param| param.0);
317317
if let (_, [duplicate, ..]) = base_params.partition_dedup() {
318318
let param = impl1_args[duplicate.0 as usize];
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//@ check-pass
2+
3+
#![feature(lazy_type_alias)]
4+
#![allow(incomplete_features)]
5+
6+
type Injective<T> = Local<T>;
7+
struct Local<T>(T);
8+
9+
impl<T> Injective<T> {
10+
fn take(_: T) {}
11+
}
12+
13+
trait Trait {
14+
type Out;
15+
fn produce() -> Self::Out;
16+
}
17+
18+
impl<T: Default> Trait for Injective<T> {
19+
type Out = T;
20+
fn produce() -> Self::Out { T::default() }
21+
}
22+
23+
fn main() {
24+
Injective::take(0);
25+
let _: String = Injective::produce();
26+
let _: bool = Local::produce();
27+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#![feature(lazy_type_alias)]
2+
#![allow(incomplete_features)]
3+
4+
impl<T> Loop<T> {} //~ ERROR the type parameter `T` is not constrained
5+
6+
type Loop<T> = Loop<T>;
7+
8+
fn main() {}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates
2+
--> $DIR/unconstrained-param-due-to-overflow.rs:4:6
3+
|
4+
LL | impl<T> Loop<T> {}
5+
| ^ unconstrained type parameter
6+
7+
error: aborting due to 1 previous error
8+
9+
For more information about this error, try `rustc --explain E0207`.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#![feature(lazy_type_alias)]
2+
#![allow(incomplete_features)]
3+
4+
impl<T> NotInjective<T> {} //~ ERROR the type parameter `T` is not constrained
5+
6+
type NotInjective<T: ?Sized> = Local<<T as Discard>::Out>;
7+
struct Local<T>(T);
8+
9+
trait Discard { type Out; }
10+
impl<T: ?Sized> Discard for T { type Out = (); }
11+
12+
fn main() {}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates
2+
--> $DIR/unconstrained-params.rs:4:6
3+
|
4+
LL | impl<T> NotInjective<T> {}
5+
| ^ unconstrained type parameter
6+
7+
error: aborting due to 1 previous error
8+
9+
For more information about this error, try `rustc --explain E0207`.

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /