Skip to content

Commit e79299f

Browse files
authored
Merge pull request #1236 from Nadrieril/improve-implexpr-builtin
Add more info to `ImplExprAtom::Builtin`
2 parents c953902 + 0abb723 commit e79299f

File tree

4 files changed

+107
-35
lines changed

4 files changed

+107
-35
lines changed

engine/lib/import_thir.ml

+7-6
Original file line numberDiff line numberDiff line change
@@ -1099,11 +1099,12 @@ end) : EXPR = struct
10991099
and c_impl_expr (span : Thir.span) (ie : Thir.impl_expr) : impl_expr =
11001100
let goal = c_trait_ref span ie.trait.value in
11011101
let impl = { kind = c_impl_expr_atom span ie.impl; goal } in
1102-
match ie.args with
1103-
| [] -> impl
1104-
| args ->
1105-
let args = List.map ~f:(c_impl_expr span) args in
1102+
match ie.impl with
1103+
| Concrete { impl_exprs = []; _ } -> impl
1104+
| Concrete { impl_exprs; _ } ->
1105+
let args = List.map ~f:(c_impl_expr span) impl_exprs in
11061106
{ kind = ImplApp { impl; args }; goal }
1107+
| _ -> impl
11071108

11081109
and c_trait_ref span (tr : Thir.trait_ref) : trait_goal =
11091110
let trait = Concrete_ident.of_def_id Trait tr.def_id in
@@ -1137,7 +1138,7 @@ end) : EXPR = struct
11371138
Parent { impl = { kind = item_kind; goal = trait_ref }; ident }
11381139
in
11391140
match ie with
1140-
| Concrete { id; generics } ->
1141+
| Concrete { id; generics; _ } ->
11411142
let trait = Concrete_ident.of_def_id Impl id in
11421143
let args = List.map ~f:(c_generic_value span) generics in
11431144
Concrete { trait; args }
@@ -1146,7 +1147,7 @@ end) : EXPR = struct
11461147
List.fold ~init ~f:browse_path path
11471148
| Dyn -> Dyn
11481149
| SelfImpl { path; _ } -> List.fold ~init:Self ~f:browse_path path
1149-
| Builtin { trait } -> Builtin (c_trait_ref span trait.value)
1150+
| Builtin { trait; _ } -> Builtin (c_trait_ref span trait.value)
11501151
| Error str -> failwith @@ "impl_expr_atom: Error " ^ str
11511152

11521153
and c_generic_value (span : Thir.span) (ty : Thir.generic_arg) : generic_value

frontend/exporter/src/traits.rs

+14-4
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ pub enum ImplExprAtom {
6262
#[from(def_id)]
6363
id: GlobalIdent,
6464
generics: Vec<GenericArg>,
65+
/// The impl exprs that prove the clauses on the impl.
66+
impl_exprs: Vec<ImplExpr>,
6567
},
6668
/// A context-bound clause like `where T: Trait`.
6769
LocalBound {
@@ -90,8 +92,18 @@ pub enum ImplExprAtom {
9092
/// `dyn Trait` implements `Trait` using a built-in implementation; this refers to that
9193
/// built-in implementation.
9294
Dyn,
93-
/// A built-in trait whose implementation is computed by the compiler, such as `Sync`.
94-
Builtin { r#trait: Binder<TraitRef> },
95+
/// A built-in trait whose implementation is computed by the compiler, such as `FnMut`. This
96+
/// morally points to an invisible `impl` block; as such it contains the information we may
97+
/// need from one.
98+
Builtin {
99+
r#trait: Binder<TraitRef>,
100+
/// The `ImplExpr`s required to satisfy the implied predicates on the trait declaration.
101+
/// E.g. since `FnMut: FnOnce`, a built-in `T: FnMut` impl would have an `ImplExpr` for `T:
102+
/// FnOnce`.
103+
impl_exprs: Vec<ImplExpr>,
104+
/// The values of the associated types for this trait.
105+
types: Vec<(DefId, Ty)>,
106+
},
95107
/// An error happened while resolving traits.
96108
Error(String),
97109
}
@@ -108,8 +120,6 @@ pub struct ImplExpr {
108120
pub r#trait: Binder<TraitRef>,
109121
/// The kind of implemention of the root of the tree.
110122
pub r#impl: ImplExprAtom,
111-
/// A list of `ImplExpr`s required to fully specify the trait references in `impl`.
112-
pub args: Vec<ImplExpr>,
113123
}
114124

115125
/// Given a clause `clause` in the context of some impl block `impl_did`, susbts correctly `Self`

frontend/exporter/src/traits/resolution.rs

+81-20
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ pub enum ImplExprAtom<'tcx> {
4949
Concrete {
5050
def_id: DefId,
5151
generics: GenericArgsRef<'tcx>,
52+
/// The impl exprs that prove the clauses on the impl.
53+
impl_exprs: Vec<ImplExpr<'tcx>>,
5254
},
5355
/// A context-bound clause like `where T: Trait`.
5456
LocalBound {
@@ -71,8 +73,18 @@ pub enum ImplExprAtom<'tcx> {
7173
/// `dyn Trait` implements `Trait` using a built-in implementation; this refers to that
7274
/// built-in implementation.
7375
Dyn,
74-
/// A built-in trait whose implementation is computed by the compiler, such as `Sync`.
75-
Builtin { r#trait: PolyTraitRef<'tcx> },
76+
/// A built-in trait whose implementation is computed by the compiler, such as `FnMut`. This
77+
/// morally points to an invisible `impl` block; as such it contains the information we may
78+
/// need from one.
79+
Builtin {
80+
r#trait: PolyTraitRef<'tcx>,
81+
/// The `ImplExpr`s required to satisfy the implied predicates on the trait declaration.
82+
/// E.g. since `FnMut: FnOnce`, a built-in `T: FnMut` impl would have an `ImplExpr` for `T:
83+
/// FnOnce`.
84+
impl_exprs: Vec<ImplExpr<'tcx>>,
85+
/// The values of the associated types for this trait.
86+
types: Vec<(DefId, Ty<'tcx>)>,
87+
},
7688
/// An error happened while resolving traits.
7789
Error(String),
7890
}
@@ -83,8 +95,6 @@ pub struct ImplExpr<'tcx> {
8395
pub r#trait: PolyTraitRef<'tcx>,
8496
/// The kind of implemention of the root of the tree.
8597
pub r#impl: ImplExprAtom<'tcx>,
86-
/// A list of `ImplExpr`s required to fully specify the trait references in `impl`.
87-
pub args: Vec<Self>,
8898
}
8999

90100
/// Items have various predicates in scope. `path_to` uses them as a starting point for trait
@@ -290,7 +300,7 @@ impl<'tcx> PredicateSearcher<'tcx> {
290300

291301
// Resolve predicates required to mention the item.
292302
let nested_impl_exprs =
293-
self.resolve_item_predicates(alias_ty.def_id, alias_ty.args, warn)?;
303+
self.resolve_item_required_predicates(alias_ty.def_id, alias_ty.args, warn)?;
294304

295305
// Add all the bounds on the corresponding associated item.
296306
self.extend(item_bounds.map(|(index, pred)| {
@@ -360,23 +370,22 @@ impl<'tcx> PredicateSearcher<'tcx> {
360370

361371
let tcx = self.tcx;
362372
let impl_source = shallow_resolve_trait_ref(tcx, self.param_env, erased_tref);
363-
let nested;
364373
let atom = match impl_source {
365374
Ok(ImplSource::UserDefined(ImplSourceUserDefinedData {
366375
impl_def_id,
367376
args: generics,
368377
..
369378
})) => {
370379
// Resolve the predicates required by the impl.
371-
nested = self.resolve_item_predicates(impl_def_id, generics, warn)?;
380+
let impl_exprs =
381+
self.resolve_item_required_predicates(impl_def_id, generics, warn)?;
372382
ImplExprAtom::Concrete {
373383
def_id: impl_def_id,
374384
generics,
385+
impl_exprs,
375386
}
376387
}
377388
Ok(ImplSource::Param(_)) => {
378-
// Mentioning a local clause requires no extra predicates to hold.
379-
nested = vec![];
380389
match self.resolve_local(erased_tref.upcast(self.tcx), warn)? {
381390
Some(candidate) => {
382391
let path = candidate.path;
@@ -402,17 +411,45 @@ impl<'tcx> PredicateSearcher<'tcx> {
402411
}
403412
}
404413
}
405-
Ok(ImplSource::Builtin(BuiltinImplSource::Object { .. }, _)) => {
406-
nested = vec![];
407-
ImplExprAtom::Dyn
408-
}
414+
Ok(ImplSource::Builtin(BuiltinImplSource::Object { .. }, _)) => ImplExprAtom::Dyn,
409415
Ok(ImplSource::Builtin(_, _)) => {
410-
// Builtin impls currently don't need nested predicates.
411-
nested = vec![];
412-
ImplExprAtom::Builtin { r#trait: *tref }
416+
// Resolve the predicates implied by the trait.
417+
let trait_def_id = erased_tref.skip_binder().def_id;
418+
// If we wanted to not skip this binder, we'd have to instantiate the bound
419+
// regions, solve, then wrap the result in a binder. And track higher-kinded
420+
// clauses better all over.
421+
let impl_exprs = self.resolve_item_implied_predicates(
422+
trait_def_id,
423+
erased_tref.skip_binder().args,
424+
warn,
425+
)?;
426+
let types = tcx
427+
.associated_items(trait_def_id)
428+
.in_definition_order()
429+
.filter(|assoc| matches!(assoc.kind, AssocKind::Type))
430+
.filter_map(|assoc| {
431+
let ty = AliasTy::new(tcx, assoc.def_id, erased_tref.skip_binder().args)
432+
.to_ty(tcx);
433+
let ty = erase_and_norm(tcx, self.param_env, ty);
434+
if let TyKind::Alias(_, alias_ty) = ty.kind() {
435+
if alias_ty.def_id == assoc.def_id {
436+
warn(&format!("Failed to compute associated type {ty}"));
437+
// We can't return the unnormalized associated type as that would
438+
// make the trait ref contain itself, which would make hax's
439+
// `sinto` infrastructure loop.
440+
return None;
441+
}
442+
}
443+
Some((assoc.def_id, ty))
444+
})
445+
.collect();
446+
ImplExprAtom::Builtin {
447+
r#trait: *tref,
448+
impl_exprs,
449+
types,
450+
}
413451
}
414452
Err(e) => {
415-
nested = vec![];
416453
let msg = format!(
417454
"Could not find a clause for `{tref:?}` in the current context: `{e:?}`"
418455
);
@@ -423,21 +460,45 @@ impl<'tcx> PredicateSearcher<'tcx> {
423460

424461
Ok(ImplExpr {
425462
r#impl: atom,
426-
args: nested,
427463
r#trait: *tref,
428464
})
429465
}
430466

431467
/// Resolve the predicates required by the given item.
432-
pub fn resolve_item_predicates(
468+
pub fn resolve_item_required_predicates(
469+
&mut self,
470+
def_id: DefId,
471+
generics: GenericArgsRef<'tcx>,
472+
// Call back into hax-related code to display a nice warning.
473+
warn: &impl Fn(&str),
474+
) -> Result<Vec<ImplExpr<'tcx>>, String> {
475+
let tcx = self.tcx;
476+
self.resolve_predicates(generics, required_predicates(tcx, def_id), warn)
477+
}
478+
479+
/// Resolve the predicates implied by the given item.
480+
pub fn resolve_item_implied_predicates(
433481
&mut self,
434482
def_id: DefId,
435483
generics: GenericArgsRef<'tcx>,
436484
// Call back into hax-related code to display a nice warning.
437485
warn: &impl Fn(&str),
438486
) -> Result<Vec<ImplExpr<'tcx>>, String> {
439487
let tcx = self.tcx;
440-
required_predicates(tcx, def_id)
488+
self.resolve_predicates(generics, implied_predicates(tcx, def_id), warn)
489+
}
490+
491+
/// Apply the given generics to the provided clauses and resolve the trait references in the
492+
/// current context.
493+
pub fn resolve_predicates(
494+
&mut self,
495+
generics: GenericArgsRef<'tcx>,
496+
predicates: GenericPredicates<'tcx>,
497+
// Call back into hax-related code to display a nice warning.
498+
warn: &impl Fn(&str),
499+
) -> Result<Vec<ImplExpr<'tcx>>, String> {
500+
let tcx = self.tcx;
501+
predicates
441502
.predicates
442503
.iter()
443504
.map(|(clause, _span)| *clause)

test-harness/src/snapshots/toolchain__traits into-fstar.snap

+5-5
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ open FStar.Mul
5555
class t_Bar (v_Self: Type0) (v_T: Type0) = { __marker_trait_t_Bar:Prims.unit }
5656

5757
class t_Foo (v_Self: Type0) = {
58-
[@@@ FStar.Tactics.Typeclasses.no_method]_super_16210070100893052778:t_Bar v_Self f_U;
58+
[@@@ FStar.Tactics.Typeclasses.no_method]_super_13496126865352171029:t_Bar v_Self f_U;
5959
f_U:Type0
6060
}
6161
'''
@@ -408,7 +408,7 @@ class t_SubTrait (v_Self: Type0) (v_TypeArg: Type0) (v_ConstArg: usize) = {
408408
v_TypeArg
409409
v_ConstArg;
410410
f_AssocType:Type0;
411-
f_AssocType_7414800425644916102:t_Trait f_AssocType v_TypeArg v_ConstArg
411+
f_AssocType_13704321474071752218:t_Trait f_AssocType v_TypeArg v_ConstArg
412412
}
413413
'''
414414
"Traits.Interlaced_consts_types.fst" = '''
@@ -485,7 +485,7 @@ open FStar.Mul
485485

486486
class t_Trait1 (v_Self: Type0) = {
487487
f_T:Type0;
488-
f_T_2328060197809802853:t_Trait1 f_T
488+
f_T_2186006717281159153:t_Trait1 f_T
489489
}
490490

491491
class t_Trait2 (v_Self: Type0) = {
@@ -630,7 +630,7 @@ let use_impl_trait (_: Prims.unit) : Prims.unit =
630630

631631
class t_Foo (v_Self: Type0) = {
632632
f_AssocType:Type0;
633-
f_AssocType_12248650268031145847:t_SuperTrait f_AssocType;
633+
f_AssocType_16668910951696008497:t_SuperTrait f_AssocType;
634634
f_N:usize;
635635
f_assoc_f_pre:Prims.unit -> Type0;
636636
f_assoc_f_post:Prims.unit -> Prims.unit -> Type0;
@@ -667,7 +667,7 @@ let g (#v_T: Type0) (#[FStar.Tactics.Typeclasses.tcresolve ()] i1: t_Foo v_T) (x
667667
let impl_Foo_for_tuple_: t_Foo Prims.unit =
668668
{
669669
f_AssocType = i32;
670-
f_AssocType_12248650268031145847 = FStar.Tactics.Typeclasses.solve;
670+
f_AssocType_16668910951696008497 = FStar.Tactics.Typeclasses.solve;
671671
f_N = sz 32;
672672
f_assoc_f_pre = (fun (_: Prims.unit) -> true);
673673
f_assoc_f_post = (fun (_: Prims.unit) (out: Prims.unit) -> true);

0 commit comments

Comments
 (0)