Skip to content

Commit c19b63c

Browse files
committed
Only FnOnce has Output
1 parent 952190a commit c19b63c

File tree

3 files changed

+114
-76
lines changed

3 files changed

+114
-76
lines changed

chalk-solve/src/clauses/builtin_traits/fn_family.rs

Lines changed: 47 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@ pub fn add_fn_family_program_clauses<I: Interner>(
2020
Some(trait_id) => trait_id,
2121
None => unreachable!(),
2222
};
23-
let trait_datum = db.trait_datum(trait_id);
24-
let output_id = trait_datum.associated_ty_ids[0];
2523

2624
match ty {
2725
TyData::Apply(apply) => match apply.name {
@@ -60,32 +58,33 @@ pub fn add_fn_family_program_clauses<I: Interner>(
6058
substitution: substitution.clone(),
6159
});
6260

63-
let alias = AliasTy::Projection(ProjectionTy {
64-
associated_ty_id: output_id,
65-
substitution,
66-
});
67-
let return_type = inputs_and_output.return_type;
68-
builder.push_fact(Normalize {
69-
alias,
70-
ty: return_type,
71-
});
61+
if let WellKnownTrait::FnOnceTrait = well_known {
62+
let trait_datum = db.trait_datum(trait_id);
63+
let output_id = trait_datum.associated_ty_ids[0];
64+
let alias = AliasTy::Projection(ProjectionTy {
65+
associated_ty_id: output_id,
66+
substitution,
67+
});
68+
let return_type = inputs_and_output.return_type;
69+
builder.push_fact(Normalize {
70+
alias,
71+
ty: return_type,
72+
});
73+
}
7274
});
7375
}
7476
TypeName::Closure(closure_id) => {
7577
let closure_datum = db.closure_datum(closure_id, apply.substitution.clone());
76-
let trait_matches = if let Some(well_known) = trait_datum.well_known {
77-
match well_known {
78-
WellKnownTrait::FnTrait => matches!(closure_datum.kind, ClosureKind::Fn),
79-
WellKnownTrait::FnOnceTrait => {
80-
matches!(closure_datum.kind, ClosureKind::FnOnce)
81-
}
82-
WellKnownTrait::FnMutTrait => {
83-
matches!(closure_datum.kind, ClosureKind::FnMut)
84-
}
85-
_ => false,
78+
let trait_matches = match well_known {
79+
WellKnownTrait::FnTrait => matches!(closure_datum.kind, ClosureKind::Fn),
80+
WellKnownTrait::FnMutTrait => {
81+
matches!(closure_datum.kind, ClosureKind::FnMut | ClosureKind::Fn)
8682
}
87-
} else {
88-
false
83+
WellKnownTrait::FnOnceTrait => matches!(
84+
closure_datum.kind,
85+
ClosureKind::FnOnce | ClosureKind::FnMut | ClosureKind::Fn
86+
),
87+
_ => false,
8988
};
9089
if trait_matches {
9190
let substitution = Substitution::from(
@@ -105,15 +104,19 @@ pub fn add_fn_family_program_clauses<I: Interner>(
105104
substitution: substitution.clone(),
106105
});
107106

108-
let alias = AliasTy::Projection(ProjectionTy {
109-
associated_ty_id: output_id,
110-
substitution,
111-
});
112-
let return_type = closure_datum.return_type.clone();
113-
builder.push_fact(Normalize {
114-
alias,
115-
ty: return_type,
116-
});
107+
if let WellKnownTrait::FnOnceTrait = well_known {
108+
let trait_datum = db.trait_datum(trait_id);
109+
let output_id = trait_datum.associated_ty_ids[0];
110+
let alias = AliasTy::Projection(ProjectionTy {
111+
associated_ty_id: output_id,
112+
substitution,
113+
});
114+
let return_type = closure_datum.return_type.clone();
115+
builder.push_fact(Normalize {
116+
alias,
117+
ty: return_type,
118+
});
119+
}
117120
}
118121
}
119122
_ => {}
@@ -146,14 +149,18 @@ pub fn add_fn_family_program_clauses<I: Interner>(
146149
substitution: substitution.clone(),
147150
});
148151

149-
let alias = AliasTy::Projection(ProjectionTy {
150-
associated_ty_id: output_id,
151-
substitution,
152-
});
153-
builder.push_fact(Normalize {
154-
alias,
155-
ty: return_type.assert_ty_ref(interner).clone(),
156-
});
152+
if let WellKnownTrait::FnOnceTrait = well_known {
153+
let trait_datum = db.trait_datum(trait_id);
154+
let output_id = trait_datum.associated_ty_ids[0];
155+
let alias = AliasTy::Projection(ProjectionTy {
156+
associated_ty_id: output_id,
157+
substitution,
158+
});
159+
builder.push_fact(Normalize {
160+
alias,
161+
ty: return_type.assert_ty_ref(interner).clone(),
162+
});
163+
}
157164
});
158165
}
159166
_ => {}

tests/test/fn_def.rs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -69,22 +69,30 @@ fn fn_def_is_clone() {
6969
fn fn_def_implements_fn_traits() {
7070
test! {
7171
program {
72-
#[lang(fn)]
73-
trait Fn<Args> { type Output; }
72+
#[lang(fnonce)]
73+
trait FnOnce<Args> {
74+
type Output;
75+
}
7476

7577
#[lang(fnmut)]
76-
trait FnMut<Args> { type Output; }
78+
trait FnMut<Args> where Self: FnOnce<Args> { }
7779

78-
#[lang(fnonce)]
79-
trait FnOnce<Args> { type Output; }
80+
#[lang(fn)]
81+
trait Fn<Args> where Self: FnMut<Args> { }
8082

8183
fn foo();
8284
fn bar(one: i32);
8385
fn baz(one: i32) -> u8;
8486
}
8587

8688
goal {
87-
foo: Fn<(), Output=()>
89+
foo: Fn<()>
90+
} yields {
91+
"Unique"
92+
}
93+
94+
goal {
95+
Normalize(<foo as FnOnce<()>>::Output -> ())
8896
} yields {
8997
"Unique"
9098
}

tests/test/functions.rs

Lines changed: 53 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -87,88 +87,111 @@ fn fn_def_implied_bounds_from_env() {
8787
fn fn_ptr_implements_fn_traits() {
8888
test! {
8989
program {
90-
#[lang(fn)]
91-
trait Fn<Args> { type Output; }
90+
#[lang(fnonce)]
91+
trait FnOnce<Args> {
92+
type Output;
93+
}
9294

9395
#[lang(fnmut)]
94-
trait FnMut<Args> { type Output; }
95-
96-
#[lang(fnonce)]
97-
trait FnOnce<Args> { type Output; }
96+
trait FnMut<Args> where Self: FnOnce<Args> { }
9897

99-
struct Foo { }
98+
#[lang(fn)]
99+
trait Fn<Args> where Self: FnMut<Args> { }
100100
}
101101

102102
goal {
103-
fn(i32): Fn<(i32,), Output=()>
103+
fn(u8): FnOnce<(u8,)>
104104
} yields {
105-
"Unique"
105+
"Unique; substitution [], lifetime constraints []"
106106
}
107+
107108
goal {
108-
fn(i32) -> (): Fn<(i32,), Output=()>
109+
fn(u8): FnMut<(u8,)>
109110
} yields {
110-
"Unique"
111+
"Unique; substitution [], lifetime constraints []"
111112
}
113+
112114
goal {
113-
fn(i32) -> u8: Fn<(i32,), Output=u8>
115+
fn(u8): Fn<(u8,)>
114116
} yields {
115-
"Unique"
117+
"Unique; substitution [], lifetime constraints []"
116118
}
119+
117120
goal {
118-
fn(i32) -> u8: Fn<(i32,), Output=()>
121+
Normalize(<fn(u8) as FnOnce<(u8,)>>::Output -> ())
119122
} yields {
120-
"No possible solution"
123+
"Unique; substitution [], lifetime constraints []"
121124
}
125+
122126
goal {
123-
fn(): FnMut<(), Output=()>
127+
Normalize(<fn(u8) -> bool as FnOnce<(u8,)>>::Output -> bool)
124128
} yields {
125-
"Unique"
129+
"Unique; substitution [], lifetime constraints []"
126130
}
131+
127132
goal {
128-
fn(): FnOnce<(), Output=()>
133+
Normalize(<fn(u8) -> bool as FnOnce<(u8,)>>::Output -> u8)
129134
} yields {
130-
"Unique"
135+
"No possible solution"
131136
}
132137

133138
goal {
134-
fn(): Fn<(i32,), Output=()>
139+
forall<T, V> {
140+
Normalize(<fn(u8, V) -> T as FnOnce<(u8, V)>>::Output -> V)
141+
}
135142
} yields {
136143
"No possible solution"
137144
}
138145

139146
goal {
140-
fn(): FnMut<(i32,), Output=()>
147+
forall<T, V> {
148+
exists<U> {
149+
Normalize(<fn(u8, V) -> T as FnOnce<(u8, V)>>::Output -> U)
150+
}
151+
}
141152
} yields {
142-
"No possible solution"
153+
"Unique; substitution [?0 := !1_0], lifetime constraints []"
154+
}
155+
156+
goal {
157+
fn(u8, u32): FnOnce<(u8,u32)>
158+
} yields {
159+
"Unique; substitution [], lifetime constraints []"
143160
}
144161

145162
goal {
146-
fn(): FnOnce<(i32,), Output=()>
163+
fn(i32): FnOnce<(bool,)>
147164
} yields {
148165
"No possible solution"
149166
}
150167

151168
goal {
152-
fn(i32, i32): Fn<(i32, i32), Output=()>
169+
forall<'a> {
170+
for<'b> fn(&'b u8): FnOnce<(&'a u8,)>
171+
}
153172
} yields {
154-
"Unique"
173+
"Unique; substitution [], lifetime constraints []"
155174
}
156175

157176
goal {
158-
fn(i32, i32, (u32, u32)): Fn<(i32, i32, (u32, u32)), Output=()>
177+
forall<'a, 'b> {
178+
for<'c> fn(&'c u8, &'c i32): FnOnce<(&'a u8, &'b i32)>
179+
}
159180
} yields {
160-
"Unique"
181+
"Unique; substitution [], lifetime constraints [InEnvironment { environment: Env([]), goal: '!1_0: '!1_1 }, InEnvironment { environment: Env([]), goal: '!1_1: '!1_0 }]"
161182
}
162183

163184
goal {
164-
fn(i32, i32, (u32, u32)): Fn<(i32, i32, (u32, u32, u32)), Output=()>
185+
forall<T, U> {
186+
fn(T, T): FnOnce<(T, U)>
187+
}
165188
} yields {
166189
"No possible solution"
167190
}
168191

169192
goal {
170-
exists<Args> {
171-
Foo: Fn<Args, Output=()>
193+
forall<T, U> {
194+
fn(T, U): FnOnce<(T, T)>
172195
}
173196
} yields {
174197
"No possible solution"

0 commit comments

Comments
 (0)