Skip to content

Commit 4ea7d0f

Browse files
authored
Fix panic from cross-crate FnDef impl-path collision (#2559)
1 parent 4c4bed7 commit 4ea7d0f

3 files changed

Lines changed: 31 additions & 14 deletions

File tree

source/rust_verify_test/tests/fndef_types.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2037,3 +2037,28 @@ test_verify_one_file_with_options! {
20372037
}
20382038
} => Ok(())
20392039
}
2040+
2041+
test_verify_one_file_with_options! {
2042+
// Regression test for a panic due to fndef impl path collision across
2043+
// crates.
2044+
//
2045+
// The test defines 12 `Clone` impls in the crate root, which are enough to
2046+
// collide with the `Clone` impls for `Ghost` and `Tracked` in
2047+
// `verus_builtin` at the same disambiguator (brought in by `["vstd"]`).
2048+
#[test] fndef_impl_path_includes_crate ["vstd"] => verus_code! {
2049+
use vstd::prelude::*;
2050+
2051+
struct S0; impl Clone for S0 { fn clone(&self) -> Self { S0 } }
2052+
struct S1; impl Clone for S1 { fn clone(&self) -> Self { S1 } }
2053+
struct S2; impl Clone for S2 { fn clone(&self) -> Self { S2 } }
2054+
struct S3; impl Clone for S3 { fn clone(&self) -> Self { S3 } }
2055+
struct S4; impl Clone for S4 { fn clone(&self) -> Self { S4 } }
2056+
struct S5; impl Clone for S5 { fn clone(&self) -> Self { S5 } }
2057+
struct S6; impl Clone for S6 { fn clone(&self) -> Self { S6 } }
2058+
struct S7; impl Clone for S7 { fn clone(&self) -> Self { S7 } }
2059+
struct S8; impl Clone for S8 { fn clone(&self) -> Self { S8 } }
2060+
struct S9; impl Clone for S9 { fn clone(&self) -> Self { S9 } }
2061+
struct S10; impl Clone for S10 { fn clone(&self) -> Self { S10 } }
2062+
struct S11; impl Clone for S11 { fn clone(&self) -> Self { S11 } }
2063+
} => Ok(())
2064+
}

source/vir/src/ast_simplify.rs

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ use crate::context::GlobalCtx;
2424
use crate::def::dummy_param_name;
2525
use crate::def::is_dummy_param_name;
2626
use crate::def::{
27-
Spanned, positional_field_ident, prefix_tuple_param, prefix_tuple_variant, user_local_name,
27+
Spanned, impl_fndef_path, positional_field_ident, prefix_tuple_param, prefix_tuple_variant,
28+
user_local_name,
2829
};
2930
use crate::messages::Span;
3031
use crate::messages::{error, internal_error};
@@ -1049,17 +1050,10 @@ fn add_fndef_axioms_to_function(
10491050
Arc::new(TypX::Datatype(tuple_dt, Arc::new(arg_typs), Arc::new(vec![])));
10501051
let trait_typ_args = Arc::new(vec![self_typ, args_tuple_typ]);
10511052

1052-
let mk_impl_path = |kind: ClosureKind| {
1053-
Arc::new(crate::ast::PathX {
1054-
krate: CrateId::Internal,
1055-
segments: Arc::new(vec![crate::def::impl_fndef(&function.x.name, kind)]),
1056-
})
1057-
};
1058-
10591053
let mut trait_impls_out: Vec<TraitImpl> = Vec::new();
10601054
for kind in [ClosureKind::Fn, ClosureKind::FnMut, ClosureKind::FnOnce] {
10611055
let trait_implx = crate::ast::TraitImplX {
1062-
impl_path: mk_impl_path(kind),
1056+
impl_path: impl_fndef_path(&function.x.name, kind),
10631057
typ_params: function.x.typ_params.clone(),
10641058
typ_bounds: function.x.typ_bounds.clone(),
10651059
trait_path: kind.trait_path(),
@@ -1074,7 +1068,7 @@ fn add_fndef_axioms_to_function(
10741068

10751069
let assoc_typ_implx = crate::ast::AssocTypeImplX {
10761070
name: Arc::new("Output".to_string()),
1077-
impl_path: mk_impl_path(ClosureKind::FnOnce),
1071+
impl_path: impl_fndef_path(&function.x.name, ClosureKind::FnOnce),
10781072
typ_params: function.x.typ_params.clone(),
10791073
typ_bounds: function.x.typ_bounds.clone(),
10801074
trait_path: ClosureKind::FnOnce.trait_path(),

source/vir/src/def.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -645,10 +645,8 @@ pub(crate) fn impl_closure(kind: ClosureKind, id: usize) -> Ident {
645645
Arc::new(format!("{}{}{}", PREFIX_IMPL_CLOSURE, kind, id))
646646
}
647647

648-
pub(crate) fn impl_fndef(fun: &Fun, kind: ClosureKind) -> Ident {
649-
let joined =
650-
fun.path.segments.iter().map(|s| s.as_str()).collect::<Vec<_>>().join(PATH_SEPARATOR);
651-
Arc::new(format!("{}{}{}", PREFIX_IMPL_FNDEF, kind, joined))
648+
pub(crate) fn impl_fndef_path(fun: &Fun, kind: ClosureKind) -> Path {
649+
fun.path.push_segment(Arc::new(format!("{}{}", PREFIX_IMPL_FNDEF, kind)))
652650
}
653651

654652
impl NameCtxt {

0 commit comments

Comments
 (0)