Skip to content
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
6 changes: 3 additions & 3 deletions spec-trait-impl/crates/spec-trait-bin/src/examples/mod.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
mod all;
mod base;
mod higher;
mod lifetimes;
mod nested;
mod order;
mod repeating;
mod sself;
mod traits;
mod types;
mod higher;

pub fn run() {
base::run();
types::run();
traits::run();
lifetimes::run();
nested::run();
repeating::run();
sself::run();
higher::run();
order::run();
Expand Down
37 changes: 0 additions & 37 deletions spec-trait-impl/crates/spec-trait-bin/src/examples/nested.rs

This file was deleted.

103 changes: 103 additions & 0 deletions spec-trait-impl/crates/spec-trait-bin/src/examples/repeating.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
use spec_trait_macro::{spec, when};

struct BaseType;

trait RepeatingGenericsTrait<T, U> {
fn repeating_generics_method(&self, _x: T, _y: U);
}

impl<T, U> RepeatingGenericsTrait<T, U> for BaseType {
fn repeating_generics_method(&self, _x: T, _y: U) {
println!("Default");
}
}

#[when(all(U = Vec<T>, T = u8))]
impl<T, U> RepeatingGenericsTrait<T, U> for BaseType {
fn repeating_generics_method(&self, _x: T, _y: U) {
println!("T is u8 and U is Vec<u8>");
}
}

#[when(U = Vec<T>)]
impl<T, U> RepeatingGenericsTrait<T, U> for BaseType {
fn repeating_generics_method(&self, _x: T, _y: U) {
println!("U is Vec<T>");
}
}

#[when(T = Vec<U>)]
impl<T, U> RepeatingGenericsTrait<T, U> for BaseType {
fn repeating_generics_method(&self, _x: T, _y: U) {
println!("T is Vec<U>");
}
}

#[when(T: Copy)]
impl<T> RepeatingGenericsTrait<T, T> for BaseType {
fn repeating_generics_method(&self, _x: T, _y: T) {
println!("T implements Copy for both parameters");
}
}

#[when(all(T = String, T = i32))]
impl<T> RepeatingGenericsTrait<T, T> for BaseType {
fn repeating_generics_method(&self, _x: T, _y: T) {
panic!("T cannot be both String and i32");
}
}

#[when(all(T = &str, T: 'a, U = &'a i32))]
impl<'a, T, U> RepeatingGenericsTrait<T, U> for BaseType {
fn repeating_generics_method(&self, _x: T, _y: U) {
println!("T and U have the same lifetime");
}
}

#[when(all(T = &str, T: 'a, U = &'b i32))]
impl<'a, 'b, T, U> RepeatingGenericsTrait<T, U> for BaseType {
fn repeating_generics_method(&self, _x: T, _y: U) {
println!("T and U have different lifetimes");
}
}

#[when(all(T = &str, T: 'static, U = for<'a> fn(T, &'a i32)))]
impl<T, U> RepeatingGenericsTrait<T, U> for BaseType {
fn repeating_generics_method(&self, x: T, y: U) {
println!("T is &'static str and U is for<'a> fn(T, &'a i32)");
}
}

#[when(all(T = &str, T: 'b, U = for<'a> fn(T, &'a i32)))]
impl<'b, T, U> RepeatingGenericsTrait<T, U> for BaseType {
fn repeating_generics_method(&self, x: T, y: U) {
println!("T is &'b str and U is for<'a> fn(T, &'a i32)");
}
}

pub fn run() {
println!("\n- Repeating Generics Examples:");

let x = BaseType;

spec! { x.repeating_generics_method(1u8, vec![2u8]); BaseType; [u8, Vec<u8>] } // "T is u8 and U is Vec<u8>"
spec! { x.repeating_generics_method(1i32, vec![2i32]); BaseType; [i32, Vec<i32>] } // "U is Vec<T>"
spec! { x.repeating_generics_method(vec![1i32], 2i32); BaseType; [Vec<i32>, i32] } // "T is Vec<U>"
spec! { x.repeating_generics_method(1i32, vec![2u8]); BaseType; [i32, Vec<u8>] } // "Default"
spec! { x.repeating_generics_method(vec![1i32], 2u8); BaseType; [Vec<i32>, u8] } // "Default"

spec! { x.repeating_generics_method(1i32, 2i32); BaseType; [i32, i32]; i32: Copy } // "T implements Copy for both parameters"
spec! { x.repeating_generics_method(1i32, 2u8); BaseType; [i32, u8]; i32: Copy; u8: Copy } // "Default"
spec! { x.repeating_generics_method(1i32, 2u8); BaseType; [i32, u8]; i32: Copy } // "Default"

spec! { x.repeating_generics_method("test", &2i32); BaseType; [&'static str, &'static i32] } // "T and U have the same lifetimes"
spec! { x.repeating_generics_method("test", &2i32); BaseType; [&'a str, &'a i32] } // "T and U have the same lifetimes"
spec! { x.repeating_generics_method("test", &2i32); BaseType; [&'static str, &'a i32] } // "T and U have different lifetimes"
spec! { x.repeating_generics_method("test", &2i32); BaseType; [&'a str, &'b i32] } // "T and U have different lifetimes"

let lambda = |_a: &str, _b: &i32| {};
spec! { x.repeating_generics_method("test", lambda); BaseType; [&'static str, for<'a> fn(&'static str, &'a i32)] } // "T is &'static str and U is for<'a> fn(T, &'a i32)"
spec! { x.repeating_generics_method("test", lambda); BaseType; [&str, for<'a> fn(&str, &'a i32)] } // "T is &'b str and U is for<'a> fn(T, &'a i32)"
spec! { x.repeating_generics_method("test", lambda); BaseType; [&'static str, for<'a> fn(&str, &'a i32)] } // "Default"
spec! { x.repeating_generics_method("test", lambda); BaseType; [&'b str, for<'a> fn(&'c str, &'a i32)] } // "Default"
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ impl<T, U, V> SelfTrait<T> for (U, V) {
}

pub fn run() {
println!("\n- Self Examples:");
println!("\n- Self Type Examples:");

let x = BaseType1;
spec! { x.self_method(42u8); BaseType1; [u8] } // -> "BaseType1: T is u8"
Expand Down
11 changes: 11 additions & 0 deletions spec-trait-impl/crates/spec-trait-bin/src/examples/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ use spec_trait_macro::{spec, when};
type MyAlias = u8;
type MyVecAlias = Vec<i32>;

trait Tr {}
impl Tr for u8 {}

struct BaseType;

trait TypesTrait<T> {
Expand Down Expand Up @@ -64,6 +67,13 @@ impl<T> TypesTrait<T> for BaseType {
}
}

#[when(T = &dyn Tr)]
impl<T> TypesTrait<T> for BaseType {
fn types_method(&self, _x: T) {
println!("T is &dyn Tr");
}
}

pub fn run() {
println!("\n- Types Examples:");

Expand All @@ -77,5 +87,6 @@ pub fn run() {
spec! { x.types_method((1, 2)); BaseType; [(i32, i32)] } // -> "T is (i32, _)"
spec! { x.types_method(&[1i32]); BaseType; [&[i32]] } // -> "T is &[i32]"
spec! { x.types_method(|x: &u8| x); BaseType; [fn(&u8) -> &u8] } // -> "T is a function pointer from &u8 to &u8"
spec! { x.types_method(&1u8); BaseType; [&dyn Tr] } // -> "T is & dyn Tr"
spec! { x.types_method(1i8); BaseType; [i8] } // -> "Default"
}
38 changes: 37 additions & 1 deletion spec-trait-impl/crates/spec-trait-macro/src/constraints.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use crate::SpecBody;
use proc_macro2::TokenStream;
use spec_trait_utils::conversions::{str_to_generics, str_to_type_name, to_string};
use spec_trait_utils::parsing::get_generics_types;
use spec_trait_utils::impls::ImplBody;
use spec_trait_utils::parsing::{count_generics, get_generics_types};
use spec_trait_utils::traits::TraitBody;
use spec_trait_utils::types::{Aliases, replace_type, strip_lifetimes, type_assignable};
use std::cmp::Ordering;
use std::collections::HashMap;
Expand Down Expand Up @@ -38,6 +41,7 @@ impl Ord for Constraint {
.then(self.traits.len().cmp(&other.traits.len()))
.then(self.not_types.len().cmp(&other.not_types.len()))
.then(self.not_traits.len().cmp(&other.not_traits.len()))
.then(count_generics(&other.generics).cmp(&count_generics(&self.generics)))
}
}

Expand Down Expand Up @@ -174,6 +178,38 @@ impl FromIterator<(String, Constraint)> for Constraints {
}
}

impl Constraints {
/// fills the constraints for each generic parameter from trait and specialized trait,
/// based on the constraints from impl and type
pub fn fill_trait_constraints(&self, spec: &SpecBody) -> Constraints {
let mut constraints = self.clone();
constraints.from_trait = self.get_trait_constraints(&spec.trait_, &spec.impl_);
constraints.from_specialized_trait = self.get_trait_constraints(
spec.trait_.specialized.as_ref().unwrap(),
spec.impl_.specialized.as_ref().unwrap(),
);
constraints.from_type = Constraint {
generics: spec.impl_.impl_generics.clone(),
type_: Some(spec.impl_.type_name.clone()),
..Default::default()
};
constraints
}

/// gets the constraints for each generic parameter from trait based on the constraints from impl
fn get_trait_constraints(&self, trait_: &TraitBody, impl_: &ImplBody) -> ConstraintMap {
let mut new_constraints = ConstraintMap::new();
for trait_generic in get_generics_types::<Vec<_>>(&trait_.generics) {
let corresponding_generic = impl_
.get_corresponding_generic(&str_to_generics(&trait_.generics), &trait_generic)
.unwrap();
let constraint = self.from_impl.get(&corresponding_generic);
new_constraints.insert(trait_generic, constraint.cloned().unwrap_or_default());
}
new_constraints
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
Loading
Loading