Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change the algorithm in validate_terminates #1220

Merged
merged 6 commits into from
Nov 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 28 additions & 1 deletion creusot-contracts-proc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,17 @@ pub fn snapshot(assertion: TS1) -> TS1 {
#[proc_macro_attribute]
pub fn terminates(_: TS1, tokens: TS1) -> TS1 {
let documentation = document_spec("terminates", TS1::new());
if let Ok(item) = syn::parse::<ImplItemFn>(tokens.clone()) {
if let Some(def) = item.defaultness {
return syn::Error::new(
def.span(),
"`terminates` functions cannot use the `default` modifier",
)
.into_compile_error()
.into();
}
};

let mut result = TS1::from(quote! { #[creusot::clause::terminates] #documentation });
result.extend(tokens);
result
Expand All @@ -434,6 +445,16 @@ pub fn terminates(_: TS1, tokens: TS1) -> TS1 {
#[proc_macro_attribute]
pub fn pure(_: TS1, tokens: TS1) -> TS1 {
let documentation = document_spec("pure", TS1::new());
if let Ok(item) = syn::parse::<ImplItemFn>(tokens.clone()) {
if let Some(def) = item.defaultness {
return syn::Error::new(
def.span(),
"`pure` functions cannot use the `default` modifier",
)
.into_compile_error()
.into();
}
};
let mut result = TS1::from(
quote! { #[creusot::clause::no_panic] #[creusot::clause::terminates] #documentation },
);
Expand Down Expand Up @@ -474,7 +495,13 @@ impl Parse for LogicInput {
let attrs = input.call(Attribute::parse_outer)?;
// Infalliable, no visibility = inherited
let vis: Visibility = input.parse()?;
let default = input.parse()?;
let default: Option<_> = input.parse()?;
if default.is_some() {
return Err(syn::Error::new(
input.span(),
"logical functions cannot use the `default` modifier",
));
}
let sig: Signature = input.parse()?;
let lookahead = input.lookahead1();
if lookahead.peek(Token![;]) {
Expand Down
25 changes: 24 additions & 1 deletion creusot/src/translation/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ impl<'tcx> TraitResolved<'tcx> {
return TraitResolved::NoInstance;
}
};
trace!("resolve_assoc_item_opt {source:?}",);
trace!("TraitResolved::resolve {source:?}",);

match source {
ImplSource::UserDefined(impl_data) => {
Expand Down Expand Up @@ -305,6 +305,29 @@ impl<'tcx> TraitResolved<'tcx> {
}
}

/// Given a trait and some type parameters, try to find a concrete `impl` block for
/// this trait.
pub(crate) fn impl_id_of_trait(
tcx: TyCtxt<'tcx>,
param_env: ParamEnv<'tcx>,
trait_def_id: DefId,
substs: GenericArgsRef<'tcx>,
) -> Option<DefId> {
let trait_ref = TraitRef::from_method(tcx, trait_def_id, substs);
let trait_ref = tcx.normalize_erasing_regions(param_env, trait_ref);

let Ok(source) = tcx.codegen_select_candidate((param_env, trait_ref)) else {
return None;
};
trace!("TraitResolved::impl_id_of_trait {source:?}",);
match source {
ImplSource::UserDefined(impl_data) => Some(impl_data.impl_def_id),
ImplSource::Param(_) => None,
// TODO: should we return something here, like we do in the above method?
ImplSource::Builtin(_, _) => None,
}
}

pub fn to_opt(
self,
did: DefId,
Expand Down
Loading
Loading